001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.types.expressions;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.psi.PsiElement;
021    import com.intellij.psi.tree.IElementType;
022    import com.intellij.psi.tree.TokenSet;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.jet.lang.descriptors.*;
026    import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
027    import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
028    import org.jetbrains.jet.lang.diagnostics.Diagnostic;
029    import org.jetbrains.jet.lang.diagnostics.Errors;
030    import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
031    import org.jetbrains.jet.lang.psi.*;
032    import org.jetbrains.jet.lang.resolve.*;
033    import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver;
034    import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver;
035    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
036    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
037    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
038    import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability;
039    import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
040    import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
041    import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
042    import org.jetbrains.jet.lang.resolve.calls.model.DataFlowInfoForArgumentsImpl;
043    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
044    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
045    import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
046    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
047    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
048    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
049    import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
050    import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
051    import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
052    import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
053    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
054    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantChecker;
055    import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant;
056    import org.jetbrains.jet.lang.resolve.name.Name;
057    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
058    import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
059    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
060    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
061    import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
062    import org.jetbrains.jet.lang.types.*;
063    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
064    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
065    import org.jetbrains.jet.lexer.JetTokens;
066    import org.jetbrains.jet.util.slicedmap.WritableSlice;
067    import org.jetbrains.jet.utils.ThrowingList;
068    
069    import java.util.Collection;
070    import java.util.Collections;
071    import java.util.List;
072    
073    import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
074    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
075    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
076    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
077    import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
078    import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
079    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
080    import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
081    import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
082    import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
083    import static org.jetbrains.jet.lang.types.expressions.TypeReconstructionUtil.reconstructBareType;
084    import static org.jetbrains.jet.lexer.JetTokens.AS_KEYWORD;
085    import static org.jetbrains.jet.lexer.JetTokens.AS_SAFE;
086    
087    @SuppressWarnings("SuspiciousMethodCalls")
088    public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
089    
090        private static final TokenSet BARE_TYPES_ALLOWED = TokenSet.create(AS_KEYWORD, AS_SAFE);
091    
092        protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade) {
093            super(facade);
094        }
095    
096        @Override
097        public JetTypeInfo visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, ExpressionTypingContext context) {
098            // TODO : other members
099            // TODO : type substitutions???
100            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
101            JetTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context);
102            JetType type = DataFlowUtils.checkType(typeInfo.getType(), expression, context);
103            ExpressionTypingUtils.checkCapturingInClosure(expression, context.trace, context.scope);
104            return JetTypeInfo.create(type, typeInfo.getDataFlowInfo()); // TODO : Extensions to this
105        }
106    
107        @Override
108        public JetTypeInfo visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, ExpressionTypingContext context) {
109            return visitParenthesizedExpression(expression, context, false);
110        }
111    
112        public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) {
113            JetExpression innerExpression = expression.getExpression();
114            if (innerExpression == null) {
115                return JetTypeInfo.create(null, context.dataFlowInfo);
116            }
117            return facade.getTypeInfo(innerExpression, context.replaceScope(context.scope), isStatement);
118        }
119    
120        @Override
121        public JetTypeInfo visitConstantExpression(@NotNull JetConstantExpression expression, ExpressionTypingContext context) {
122            CompileTimeConstant<?> value = ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, context.expectedType);
123    
124            if (!(value instanceof IntegerValueTypeConstant)) {
125                CompileTimeConstantChecker compileTimeConstantChecker = context.getCompileTimeConstantChecker();
126                boolean hasError = compileTimeConstantChecker.checkConstantExpressionType(value, expression, context.expectedType);
127                if (hasError) {
128                    IElementType elementType = expression.getNode().getElementType();
129                    return JetTypeInfo.create(getDefaultType(elementType), context.dataFlowInfo);
130                }
131            }
132    
133            assert value != null : "CompileTimeConstant should be evaluated for constant expression or an error should be recorded " + expression.getText();
134            return createCompileTimeConstantTypeInfo(value, expression, context);
135        }
136    
137        @Override
138        public JetTypeInfo visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) {
139            ExpressionTypingContext contextWithNoExpectedType =
140                    context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
141            JetExpression left = expression.getLeft();
142            JetTypeReference right = expression.getRight();
143            if (right == null) {
144                JetTypeInfo leftTypeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
145                return JetTypeInfo.create(null, leftTypeInfo.getDataFlowInfo());
146            }
147    
148            IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
149    
150            boolean allowBareTypes = BARE_TYPES_ALLOWED.contains(operationType);
151            TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, allowBareTypes);
152            PossiblyBareType possiblyBareTarget = components.expressionTypingServices.getTypeResolver().resolvePossiblyBareType(typeResolutionContext, right);
153    
154            if (operationType == JetTokens.COLON) {
155                // We do not allow bare types on static assertions, because static assertions provide an expected type for their argument,
156                // thus causing a circularity in type dependencies
157                assert !possiblyBareTarget.isBare() : "Bare types should not be allowed for static assertions, because argument inference makes no sense there";
158                JetType targetType = possiblyBareTarget.getActualType();
159    
160                JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
161                checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
162                return DataFlowUtils.checkType(targetType, expression, context, typeInfo.getDataFlowInfo());
163            }
164    
165            JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
166    
167            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
168            JetType subjectType = typeInfo.getType();
169            JetType targetType = reconstructBareType(right, possiblyBareTarget, subjectType, context.trace);
170    
171            if (subjectType != null) {
172                checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, subjectType);
173                dataFlowInfo = typeInfo.getDataFlowInfo();
174                if (operationType == AS_KEYWORD) {
175                    DataFlowValue value = DataFlowValueFactory.createDataFlowValue(left, subjectType, context.trace.getBindingContext());
176                    dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType);
177                }
178            }
179    
180            JetType result = operationType == AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
181            return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
182        }
183    
184        private void checkBinaryWithTypeRHS(
185                @NotNull JetBinaryExpressionWithTypeRHS expression,
186                @NotNull ExpressionTypingContext context,
187                @NotNull JetType targetType,
188                @Nullable JetType actualType
189        ) {
190            if (actualType == null) return;
191            JetSimpleNameExpression operationSign = expression.getOperationReference();
192            IElementType operationType = operationSign.getReferencedNameElementType();
193            if (operationType == JetTokens.COLON) {
194                return;
195            }
196            if (operationType != JetTokens.AS_KEYWORD && operationType != JetTokens.AS_SAFE) {
197                context.trace.report(UNSUPPORTED.on(operationSign, "binary operation with type RHS"));
198                return;
199            }
200            checkForCastImpossibility(expression, actualType, targetType, context);
201        }
202    
203        private void checkForCastImpossibility(
204                JetBinaryExpressionWithTypeRHS expression,
205                JetType actualType,
206                JetType targetType,
207                ExpressionTypingContext context
208        ) {
209            if (actualType == null || noExpectedType(targetType)) return;
210    
211            if (!CastDiagnosticsUtil.isCastPossible(actualType, targetType, components.platformToKotlinClassMap)) {
212                context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference()));
213            }
214            else {
215                JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
216                // Upcast?
217                if (typeChecker.isSubtypeOf(actualType, targetType)) {
218                    if (!typeChecker.isSubtypeOf(targetType, actualType)) {
219                        // proper upcast: String as Any
220                        context.trace.report(USELESS_CAST_STATIC_ASSERT_IS_FINE.on(expression.getOperationReference()));
221                    }
222                    else {
223                        // cast to itself: String as String
224                        context.trace.report(USELESS_CAST.on(expression.getOperationReference()));
225                    }
226                }
227                else if (CastDiagnosticsUtil.isCastErased(actualType, targetType, typeChecker)) {
228                    context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType));
229                }
230            }
231        }
232    
233        @Override
234        public JetTypeInfo visitThisExpression(@NotNull JetThisExpression expression, ExpressionTypingContext context) {
235            JetType result = null;
236            LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, false);
237    
238            switch (resolutionResult.getCode()) {
239                case LABEL_RESOLUTION_ERROR:
240                    // Do nothing, the error is already reported
241                    break;
242                case NO_THIS:
243                    context.trace.report(NO_THIS.on(expression));
244                    break;
245                case SUCCESS:
246                    result = resolutionResult.getReceiverParameterDescriptor().getType();
247                    context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
248                    break;
249            }
250            return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
251        }
252    
253        @Override
254        public JetTypeInfo visitSuperExpression(@NotNull JetSuperExpression expression, ExpressionTypingContext context) {
255            LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, true);
256    
257            if (!JetPsiUtil.isLHSOfDot(expression)) {
258                context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText()));
259                return errorInSuper(expression, context);
260            }
261    
262            switch (resolutionResult.getCode()) {
263                case LABEL_RESOLUTION_ERROR:
264                    // The error is already reported
265                    return errorInSuper(expression, context);
266                case NO_THIS:
267                    context.trace.report(SUPER_NOT_AVAILABLE.on(expression));
268                    return errorInSuper(expression, context);
269                case SUCCESS:
270                    JetType result = checkPossiblyQualifiedSuper(expression, context, resolutionResult.getReceiverParameterDescriptor());
271                    if (result != null) {
272                        context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
273                    }
274                    return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
275            }
276            throw new IllegalStateException("Unknown code: " + resolutionResult.getCode());
277        }
278    
279        private JetTypeInfo errorInSuper(JetSuperExpression expression, ExpressionTypingContext context) {
280            JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
281            if (superTypeQualifier != null) {
282                components.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true);
283            }
284            return JetTypeInfo.create(null, context.dataFlowInfo);
285        }
286    
287        private JetType checkPossiblyQualifiedSuper(
288                JetSuperExpression expression,
289                ExpressionTypingContext context,
290                ReceiverParameterDescriptor thisReceiver
291        ) {
292            JetType result = null;
293            JetType thisType = thisReceiver.getType();
294            Collection<JetType> supertypes = thisType.getConstructor().getSupertypes();
295            TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
296    
297            JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
298            if (superTypeQualifier != null) {
299                JetTypeElement typeElement = superTypeQualifier.getTypeElement();
300    
301                DeclarationDescriptor classifierCandidate = null;
302                JetType supertype = null;
303                PsiElement redundantTypeArguments = null;
304                if (typeElement instanceof JetUserType) {
305                    JetUserType userType = (JetUserType) typeElement;
306                    // This may be just a superclass name even if the superclass is generic
307                    if (userType.getTypeArguments().isEmpty()) {
308                        classifierCandidate = components.expressionTypingServices.getTypeResolver().resolveClass(context.scope, userType, context.trace);
309                    }
310                    else {
311                        supertype = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true);
312                        redundantTypeArguments = userType.getTypeArgumentList();
313                    }
314                }
315                else {
316                    supertype = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true);
317                }
318    
319                if (supertype != null) {
320                    if (supertypes.contains(supertype)) {
321                        result = supertype;
322                    }
323                }
324                else if (classifierCandidate instanceof ClassDescriptor) {
325                    ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
326    
327                    for (JetType declaredSupertype : supertypes) {
328                        if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
329                            result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
330                            break;
331                        }
332                    }
333                }
334    
335                boolean validClassifier = classifierCandidate != null && !ErrorUtils.isError(classifierCandidate);
336                boolean validType = supertype != null && !supertype.isError();
337                if (result == null && (validClassifier || validType)) {
338                    context.trace.report(NOT_A_SUPERTYPE.on(superTypeQualifier));
339                }
340                else if (redundantTypeArguments != null) {
341                    context.trace.report(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER.on(redundantTypeArguments));
342                }
343            }
344            else {
345                if (supertypes.size() > 1) {
346                    context.trace.report(AMBIGUOUS_SUPER.on(expression));
347                }
348                else {
349                    // supertypes may be empty when all the supertypes are error types (are not resolved, for example)
350                    JetType type = supertypes.isEmpty()
351                                   ? KotlinBuiltIns.getInstance().getAnyType()
352                                   : supertypes.iterator().next();
353                    result = substitutor.substitute(type, Variance.INVARIANT);
354                }
355            }
356            if (result != null) {
357                if (DescriptorUtils.isTrait(thisType.getConstructor().getDeclarationDescriptor())) {
358                    if (DescriptorUtils.isClass(result.getConstructor().getDeclarationDescriptor())) {
359                        context.trace.report(SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT.on(expression));
360                    }
361                }
362                context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
363                context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
364                if (superTypeQualifier != null) {
365                    context.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, superTypeQualifier, context.scope);
366                }
367            }
368            return result;
369        }
370    
371        @NotNull // No class receivers
372        private static LabelResolver.LabeledReceiverResolutionResult resolveToReceiver(
373                JetInstanceExpressionWithLabel expression,
374                ExpressionTypingContext context,
375                boolean onlyClassReceivers
376        ) {
377            String labelName = expression.getLabelName();
378            if (labelName != null) {
379                LabelResolver.LabeledReceiverResolutionResult resolutionResult =
380                        LabelResolver.INSTANCE.resolveThisOrSuperLabel(expression, context, Name.identifier(labelName));
381                if (onlyClassReceivers && resolutionResult.success()) {
382                    if (!isDeclaredInClass(resolutionResult.getReceiverParameterDescriptor())) {
383                        return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(NO_RECEIVER_PARAMETER);
384                    }
385                }
386                return resolutionResult;
387            }
388            else {
389                ReceiverParameterDescriptor result = NO_RECEIVER_PARAMETER;
390                List<ReceiverParameterDescriptor> receivers = context.scope.getImplicitReceiversHierarchy();
391                if (onlyClassReceivers) {
392                    for (ReceiverParameterDescriptor receiver : receivers) {
393                        if (isDeclaredInClass(receiver)) {
394                            result = receiver;
395                            break;
396                        }
397                    }
398                }
399                else if (!receivers.isEmpty()) {
400                    result = receivers.get(0);
401                }
402                if (result != NO_RECEIVER_PARAMETER) {
403                    context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration());
404                    recordThisOrSuperCallInTraceAndCallExtension(context, result, expression);
405    
406                }
407                return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result);
408            }
409        }
410    
411        private static void recordThisOrSuperCallInTraceAndCallExtension(
412                ExpressionTypingContext context,
413                ReceiverParameterDescriptor descriptor,
414                JetExpression expression
415        ) {
416            BindingTrace trace = context.trace;
417            Call call = CallMaker.makeCall(expression, NO_RECEIVER, null, expression, Collections.<ValueArgument>emptyList());
418            ResolutionCandidate<ReceiverParameterDescriptor> resolutionCandidate =
419                    ResolutionCandidate.create(
420                            call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false);
421    
422            ResolvedCallImpl<ReceiverParameterDescriptor> resolvedCall =
423                    ResolvedCallImpl.create(resolutionCandidate,
424                                            TemporaryBindingTrace.create(trace, "Fake trace for fake 'this' or 'super' resolved call"),
425                                            TracingStrategy.EMPTY,
426                                            new DataFlowInfoForArgumentsImpl(call));
427            resolvedCall.markCallAsCompleted();
428    
429            trace.record(RESOLVED_CALL, expression, resolvedCall);
430            trace.record(CALL, expression, call);
431    
432            context.callResolverExtension.run(resolvedCall,
433                                              BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.DISABLED));
434        }
435    
436        private static boolean isDeclaredInClass(ReceiverParameterDescriptor receiver) {
437            return receiver.getContainingDeclaration() instanceof ClassDescriptor;
438        }
439    
440        @Override
441        public JetTypeInfo visitBlockExpression(@NotNull JetBlockExpression expression, ExpressionTypingContext context) {
442            return components.expressionTypingServices.getBlockReturnedType(expression, context, false);
443        }
444    
445        @Override
446        public JetTypeInfo visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, ExpressionTypingContext context) {
447            JetTypeReference typeReference = expression.getTypeReference();
448    
449            JetType receiverType =
450                    typeReference == null
451                    ? null
452                    : components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, false);
453    
454            JetSimpleNameExpression callableReference = expression.getCallableReference();
455            if (callableReference.getReferencedName().isEmpty()) {
456                context.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference));
457                JetType errorType = ErrorUtils.createErrorType("Empty callable reference");
458                return DataFlowUtils.checkType(errorType, expression, context, context.dataFlowInfo);
459            }
460    
461            JetType result = getCallableReferenceType(expression, receiverType, context);
462            return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
463        }
464    
465        @Nullable
466        private JetType getCallableReferenceType(
467                @NotNull JetCallableReferenceExpression expression,
468                @Nullable JetType lhsType,
469                @NotNull ExpressionTypingContext context
470        ) {
471            JetSimpleNameExpression reference = expression.getCallableReference();
472    
473            boolean[] result = new boolean[1];
474            FunctionDescriptor descriptor = resolveCallableReferenceTarget(lhsType, context, expression, result);
475    
476            if (!result[0]) {
477                context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
478            }
479            if (descriptor == null) return null;
480    
481            ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
482            ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
483            if (receiverParameter != null && expectedThisObject != null) {
484                context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, descriptor));
485                return null;
486            }
487    
488            JetType receiverType = null;
489            if (receiverParameter != null) {
490                receiverType = receiverParameter.getType();
491            }
492            else if (expectedThisObject != null) {
493                receiverType = expectedThisObject.getType();
494            }
495    
496            //noinspection ConstantConditions
497            JetType type = components.reflectionTypes.getKFunctionType(
498                    Annotations.EMPTY,
499                    receiverType,
500                    DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()),
501                    descriptor.getReturnType(),
502                    receiverParameter != null
503            );
504    
505            if (type.isError()) {
506                context.trace.report(REFLECTION_TYPES_NOT_LOADED.on(expression.getDoubleColonTokenReference()));
507                return null;
508            }
509    
510            AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
511                    context.scope.getContainingDeclaration(),
512                    Annotations.EMPTY,
513                    CallableMemberDescriptor.Kind.DECLARATION);
514    
515            FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
516    
517            context.trace.record(FUNCTION, expression, functionDescriptor);
518    
519            return type;
520        }
521    
522        @Nullable
523        private FunctionDescriptor resolveCallableReferenceTarget(
524                @Nullable JetType lhsType,
525                @NotNull ExpressionTypingContext context,
526                @NotNull JetCallableReferenceExpression expression,
527                @NotNull boolean[] result
528        ) {
529            JetSimpleNameExpression reference = expression.getCallableReference();
530    
531            if (lhsType == null) {
532                return resolveCallableNotCheckingArguments(reference, NO_RECEIVER, context, result);
533            }
534    
535            ClassifierDescriptor classifier = lhsType.getConstructor().getDeclarationDescriptor();
536            if (!(classifier instanceof ClassDescriptor)) {
537                context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(expression));
538                return null;
539            }
540    
541            ReceiverValue receiver = new TransientReceiver(lhsType);
542            TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
543                    context, "trace to resolve callable reference with receiver", reference);
544            FunctionDescriptor descriptor = resolveCallableNotCheckingArguments(
545                    reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
546            if (result[0]) {
547                temporaryWithReceiver.commit();
548                return descriptor;
549            }
550    
551            JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier);
552            TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
553                    context, "trace to resolve callable reference in static scope", reference);
554            FunctionDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
555                    context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
556            if (result[0]) {
557                temporaryForStatic.commit();
558                return possibleStaticNestedClassConstructor;
559            }
560    
561            return null;
562        }
563    
564        @Nullable
565        private FunctionDescriptor resolveCallableNotCheckingArguments(
566                @NotNull JetSimpleNameExpression reference,
567                @NotNull ReceiverValue receiver,
568                @NotNull ExpressionTypingContext context,
569                @NotNull boolean[] result
570        ) {
571            Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
572    
573            TemporaryBindingTrace trace = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", reference);
574    
575            ExpressionTypingContext contextForResolve = context.replaceBindingTrace(trace).replaceExpectedType(NO_EXPECTED_TYPE);
576            ResolvedCall<FunctionDescriptor> function = components.expressionTypingServices.getCallExpressionResolver()
577                    .getResolvedCallForFunction(call, reference, contextForResolve, CheckValueArgumentsMode.DISABLED, result);
578            if (!result[0]) return null;
579    
580            if (function instanceof VariableAsFunctionResolvedCall) {
581                // TODO: KProperty
582                context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
583                context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
584                return null;
585            }
586    
587            trace.commit();
588            return function != null ? function.getResultingDescriptor() : null;
589        }
590    
591        @Override
592        public JetTypeInfo visitQualifiedExpression(@NotNull JetQualifiedExpression expression, ExpressionTypingContext context) {
593            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
594            return callExpressionResolver.getQualifiedExpressionTypeInfo(expression, context);
595        }
596    
597        @Override
598        public JetTypeInfo visitCallExpression(@NotNull JetCallExpression expression, ExpressionTypingContext context) {
599            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
600            return callExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context);
601        }
602    
603        @Override
604        public JetTypeInfo visitUnaryExpression(@NotNull JetUnaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
605            ExpressionTypingContext context = isUnaryExpressionDependentOnExpectedType(expression)
606                    ? contextWithExpectedType
607                    : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
608    
609            JetExpression baseExpression = expression.getBaseExpression();
610            if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
611    
612            JetSimpleNameExpression operationSign = expression.getOperationReference();
613    
614            IElementType operationType = operationSign.getReferencedNameElementType();
615    
616            // Special case for expr!!
617            if (operationType == JetTokens.EXCLEXCL) {
618                return visitExclExclExpression(expression, context);
619            }
620    
621            // Type check the base expression
622            JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context);
623            JetType type = typeInfo.getType();
624            if (type == null) {
625                return typeInfo;
626            }
627            DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
628    
629            // Conventions for unary operations
630            Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
631            if (name == null) {
632                context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
633                return JetTypeInfo.create(null, dataFlowInfo);
634            }
635    
636            // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
637            if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) {
638                JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
639                resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression,
640                                            stubExpression,
641                                            context.replaceBindingTrace(
642                                                    TemporaryBindingTrace.create(context.trace, "trace to resolve array access set method for unary expression", expression)),
643                                            context.trace);
644            }
645    
646            ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type);
647    
648            // Resolve the operation reference
649            OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(
650                    context,
651                    CallMaker.makeCall(receiver, expression),
652                    expression.getOperationReference(),
653                    name);
654    
655            if (!resolutionResults.isSuccess()) {
656                return JetTypeInfo.create(null, dataFlowInfo);
657            }
658    
659            // Computing the return type
660            JetType returnType = resolutionResults.getResultingDescriptor().getReturnType();
661            JetType result;
662            if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
663                assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
664                if (JetTypeChecker.INSTANCE.isSubtypeOf(returnType, KotlinBuiltIns.getInstance().getUnitType())) {
665                    result = ErrorUtils.createErrorType(KotlinBuiltIns.getInstance().getUnit().getName().asString());
666                    context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
667                }
668                else {
669                    JetType receiverType = receiver.getType();
670                    if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, receiverType)) {
671                        context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
672                    }
673                    else {
674                        context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
675    
676                        checkLValue(context.trace, baseExpression);
677                    }
678                    // TODO : Maybe returnType?
679                    result = receiverType;
680                }
681            }
682            else {
683                result = returnType;
684            }
685    
686            CompileTimeConstant<?> value = ConstantExpressionEvaluator.object$.evaluate(expression, contextWithExpectedType.trace,
687                                                                                        contextWithExpectedType.expectedType);
688            if (value != null) {
689                return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
690            }
691    
692            return DataFlowUtils.checkType(result, expression, contextWithExpectedType, dataFlowInfo);
693        }
694    
695        @NotNull
696        public static JetTypeInfo createCompileTimeConstantTypeInfo(
697                @NotNull CompileTimeConstant<?> value,
698                @NotNull JetExpression expression,
699                @NotNull ExpressionTypingContext context
700        ) {
701            JetType expressionType = value.getType(KotlinBuiltIns.getInstance());
702            if (value instanceof IntegerValueTypeConstant && context.contextDependency == INDEPENDENT) {
703                expressionType = ((IntegerValueTypeConstant) value).getType(context.expectedType);
704                ArgumentTypeResolver.updateNumberType(expressionType, expression, context.trace);
705            }
706    
707            return DataFlowUtils.checkType(expressionType, expression, context, context.dataFlowInfo);
708        }
709    
710        private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) {
711            JetExpression baseExpression = expression.getBaseExpression();
712            assert baseExpression != null;
713            JetSimpleNameExpression operationSign = expression.getOperationReference();
714            assert operationSign.getReferencedNameElementType() == JetTokens.EXCLEXCL;
715    
716            Call call = createCallForSpecialConstruction(expression, Collections.singletonList(baseExpression));
717            components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
718                    call, "ExclExcl", Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null);
719            JetTypeInfo baseTypeInfo = BindingContextUtils.getRecordedTypeInfo(baseExpression, context.trace.getBindingContext());
720            assert baseTypeInfo != null : "Base expression was not processed: " + expression;
721            JetType baseType = baseTypeInfo.getType();
722            if (baseType == null) {
723                return baseTypeInfo;
724            }
725            DataFlowInfo dataFlowInfo = baseTypeInfo.getDataFlowInfo();
726            if (isKnownToBeNotNull(baseExpression, context) && !baseType.isError()) {
727                context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, baseType));
728            }
729            else {
730                DataFlowValue value = DataFlowValueFactory.createDataFlowValue(baseExpression, baseType, context.trace.getBindingContext());
731                dataFlowInfo = dataFlowInfo.disequate(value, DataFlowValue.NULL);
732            }
733            return JetTypeInfo.create(TypeUtils.makeNotNullable(baseType), dataFlowInfo);
734        }
735    
736        @Override
737        public JetTypeInfo visitLabeledExpression(
738                @NotNull JetLabeledExpression expression, ExpressionTypingContext context
739        ) {
740            return visitLabeledExpression(expression, context, false);
741        }
742    
743        @NotNull
744        public JetTypeInfo visitLabeledExpression(
745                @NotNull JetLabeledExpression expression,
746                @NotNull ExpressionTypingContext context,
747                boolean isStatement
748        ) {
749            JetExpression baseExpression = expression.getBaseExpression();
750            if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
751    
752            return facade.getTypeInfo(baseExpression, context, isStatement);
753        }
754    
755        private static boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) {
756            JetType type = context.trace.get(EXPRESSION_TYPE, expression);
757            assert type != null : "This method is only supposed to be called when the type is not null";
758            return isKnownToBeNotNull(expression, type, context);
759        }
760    
761        private static boolean isKnownToBeNotNull(JetExpression expression, JetType jetType, ExpressionTypingContext context) {
762            DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, jetType, context.trace.getBindingContext());
763            return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull();
764        }
765    
766        public static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) {
767            checkLValue(trace, expression, false);
768        }
769    
770        private static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expressionWithParenthesis, boolean canBeThis) {
771            JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
772            if (expression instanceof JetArrayAccessExpression) {
773                JetExpression arrayExpression = ((JetArrayAccessExpression) expression).getArrayExpression();
774                if (arrayExpression != null) {
775                    checkLValue(trace, arrayExpression, true);
776                }
777                return;
778            }
779            if (canBeThis && expression instanceof JetThisExpression) return;
780            VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
781    
782            JetExpression reportOn = expression != null ? expression : expressionWithParenthesis;
783            if (variable instanceof PropertyDescriptor) {
784                PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
785                if (propertyDescriptor.isSetterProjectedOut()) {
786                    trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
787                }
788            }
789    
790            if (variable == null) {
791                trace.report(VARIABLE_EXPECTED.on(reportOn));
792            }
793        }
794    
795        @Override
796        public JetTypeInfo visitBinaryExpression(@NotNull JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
797            ExpressionTypingContext context = isBinaryExpressionDependentOnExpectedType(expression)
798                    ? contextWithExpectedType
799                    : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
800    
801            JetSimpleNameExpression operationSign = expression.getOperationReference();
802            JetExpression left = expression.getLeft();
803            JetExpression right = expression.getRight();
804            IElementType operationType = operationSign.getReferencedNameElementType();
805    
806            JetTypeInfo result;
807    
808            //Expressions that can depend on expected type
809            if (operationType == JetTokens.IDENTIFIER) {
810                Name referencedName = operationSign.getReferencedNameAsName();
811                result = getTypeInfoForBinaryCall(referencedName, context, expression);
812            }
813            else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) {
814                Name referencedName = OperatorConventions.BINARY_OPERATION_NAMES.get(operationType);
815                result = getTypeInfoForBinaryCall(referencedName, context, expression);
816            }
817            else if (operationType == JetTokens.ELVIS) {
818                //base expression of elvis operator is checked for 'type mismatch', so the whole expression shouldn't be checked
819                return visitElvisExpression(expression, context);
820            }
821    
822            //Expressions that don't depend on expected type
823            else if (operationType == JetTokens.EQ) {
824                result = visitAssignment(expression, context);
825            }
826            else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
827                result = visitAssignmentOperation(expression, context);
828            }
829            else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
830                result = visitComparison(expression, context, operationSign);
831            }
832            else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
833                result = visitEquality(expression, context, operationSign, left, right);
834            }
835            else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
836                ensureNonemptyIntersectionOfOperandTypes(expression, context);
837                // TODO : Check comparison pointlessness
838                result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), context.dataFlowInfo);
839            }
840            else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
841                result = checkInExpression(expression, operationSign, left, right, context);
842            }
843            else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
844                result = visitBooleanOperationExpression(operationType, left, right, context);
845            }
846            else {
847                context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
848                result = JetTypeInfo.create(null, context.dataFlowInfo);
849            }
850            CompileTimeConstant<?> value = ConstantExpressionEvaluator.object$.
851                    evaluate(expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType);
852            if (value != null) {
853                return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
854            }
855            return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
856        }
857    
858        private JetTypeInfo visitEquality(
859                JetBinaryExpression expression,
860                ExpressionTypingContext context,
861                JetSimpleNameExpression operationSign,
862                final JetExpression left,
863                final JetExpression right
864        ) {
865            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
866            if (right == null || left == null) {
867                ExpressionTypingUtils.getTypeInfoOrNullType(right, context, facade);
868                ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
869                return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo);
870            }
871            ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context);
872    
873            JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
874    
875            dataFlowInfo = leftTypeInfo.getDataFlowInfo();
876            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
877    
878            JetTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithDataFlow);
879            dataFlowInfo = rightTypeInfo.getDataFlowInfo();
880    
881            TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create(
882                    context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
883            traceInterpretingRightAsNullableAny.record(EXPRESSION_TYPE, right, KotlinBuiltIns.getInstance().getNullableAnyType());
884    
885            Call call = CallMaker.makeCallWithExpressions(operationSign, receiver, null, operationSign, Collections.singletonList(right));
886            ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
887            OverloadResolutionResults<FunctionDescriptor> resolutionResults =
888                    components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorConventions.EQUALS);
889    
890            traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() {
891                @Override
892                public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
893                    // the type of the right expression isn't 'Any?' actually
894                    if (key == right && slice == EXPRESSION_TYPE) return false;
895    
896                    // a hack due to KT-678
897                    // without this line an autocast is reported on the receiver (if it was previously checked for not-null)
898                    // with not-null check the resolution result changes from 'fun Any?.equals' to 'equals' member
899                    if (key == left && slice == AUTOCAST) return false;
900    
901                    return true;
902                }
903            }, true);
904    
905            if (resolutionResults.isSuccess()) {
906                FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
907                if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(), context)) {
908                    ensureNonemptyIntersectionOfOperandTypes(expression, context);
909                }
910            }
911            else {
912                if (resolutionResults.isAmbiguity()) {
913                    context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls()));
914                }
915                else {
916                    context.trace.report(EQUALS_MISSING.on(operationSign));
917                }
918            }
919            return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo);
920        }
921    
922        @NotNull
923        private JetTypeInfo visitComparison(
924                @NotNull JetBinaryExpression expression,
925                @NotNull ExpressionTypingContext context,
926                @NotNull JetSimpleNameExpression operationSign
927        ) {
928            JetTypeInfo typeInfo = getTypeInfoForBinaryCall(OperatorConventions.COMPARE_TO, context, expression);
929            DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
930            JetType compareToReturnType = typeInfo.getType();
931            JetType type = null;
932            if (compareToReturnType != null && !compareToReturnType.isError()) {
933                TypeConstructor constructor = compareToReturnType.getConstructor();
934                KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
935                TypeConstructor intTypeConstructor = builtIns.getInt().getTypeConstructor();
936                if (constructor.equals(intTypeConstructor)) {
937                    type = builtIns.getBooleanType();
938                }
939                else {
940                    context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType));
941                }
942            }
943            return JetTypeInfo.create(type, dataFlowInfo);
944        }
945    
946        @NotNull
947        private JetTypeInfo visitBooleanOperationExpression(
948                @Nullable IElementType operationType,
949                @Nullable JetExpression left,
950                @Nullable JetExpression right,
951                @NotNull ExpressionTypingContext context
952        ) {
953            JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
954            JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context.replaceExpectedType(booleanType), facade);
955            DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
956    
957            WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||");
958            // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
959            boolean isAnd = operationType == JetTokens.ANDAND;
960            DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
961            WritableScopeImpl rightScope = isAnd ? leftScope : newWritableScopeImpl(context, "Right scope of && or ||");
962    
963            ExpressionTypingContext contextForRightExpr =
964                    context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope).replaceExpectedType(booleanType);
965            if (right != null) {
966                facade.getTypeInfo(right, contextForRightExpr);
967            }
968            return JetTypeInfo.create(booleanType, dataFlowInfo);
969        }
970    
971        @NotNull
972        private JetTypeInfo visitElvisExpression(
973                @NotNull JetBinaryExpression expression,
974                @NotNull ExpressionTypingContext contextWithExpectedType
975        ) {
976            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
977            JetExpression left = expression.getLeft();
978            JetExpression right = expression.getRight();
979    
980            if (left == null || right == null) {
981                getTypeInfoOrNullType(left, context, facade);
982                return JetTypeInfo.create(null, context.dataFlowInfo);
983            }
984    
985            Call call = createCallForSpecialConstruction(expression, Lists.newArrayList(left, right));
986            ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
987                    call, "Elvis", Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
988            JetTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
989            assert leftTypeInfo != null : "Left expression was not processed: " + expression;
990            JetType leftType = leftTypeInfo.getType();
991            if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
992                context.trace.report(USELESS_ELVIS.on(left, leftType));
993            }
994            JetTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext());
995            assert rightTypeInfo != null : "Right expression was not processed: " + expression;
996            JetType rightType = rightTypeInfo.getType();
997    
998            DataFlowInfo dataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
999            JetType type = resolvedCall.getResultingDescriptor().getReturnType();
1000            if (type == null || rightType == null) return JetTypeInfo.create(null, dataFlowInfo);
1001    
1002            return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified(type, rightType.isNullable()), dataFlowInfo);
1003        }
1004    
1005        @NotNull
1006        public JetTypeInfo checkInExpression(
1007                @NotNull JetElement callElement,
1008                @NotNull JetSimpleNameExpression operationSign,
1009                @Nullable JetExpression left,
1010                @Nullable JetExpression right,
1011                @NotNull ExpressionTypingContext context
1012        ) {
1013            ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
1014            if (right == null) {
1015                if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
1016                return JetTypeInfo.create(null, context.dataFlowInfo);
1017            }
1018    
1019            DataFlowInfo dataFlowInfo = facade.getTypeInfo(right, contextWithNoExpectedType).getDataFlowInfo();
1020    
1021            ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, contextWithNoExpectedType);
1022            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1023    
1024            OverloadResolutionResults<FunctionDescriptor> resolutionResult = components.callResolver.resolveCallWithGivenName(
1025                    contextWithDataFlow,
1026                    CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)),
1027                    operationSign,
1028                    OperatorConventions.CONTAINS);
1029            JetType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
1030            ensureBooleanResult(operationSign, OperatorConventions.CONTAINS, containsType, context);
1031    
1032            if (left != null) {
1033                dataFlowInfo = facade.getTypeInfo(left, contextWithDataFlow).getDataFlowInfo().and(dataFlowInfo);
1034            }
1035    
1036            return JetTypeInfo.create(resolutionResult.isSuccess() ? KotlinBuiltIns.getInstance().getBooleanType() : null, dataFlowInfo);
1037        }
1038    
1039        private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
1040            JetExpression left = expression.getLeft();
1041            if (left == null) return;
1042    
1043            JetExpression right = expression.getRight();
1044    
1045            // TODO : duplicated effort for == and !=
1046            JetType leftType = facade.getTypeInfo(left, context).getType();
1047            if (leftType != null && right != null) {
1048                JetType rightType = facade.getTypeInfo(right, context).getType();
1049    
1050                if (rightType != null) {
1051                    if (TypeUtils.isIntersectionEmpty(leftType, rightType)) {
1052                        context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType));
1053                    }
1054                    checkSenselessComparisonWithNull(expression, left, right, context);
1055                }
1056            }
1057        }
1058    
1059        private void checkSenselessComparisonWithNull(@NotNull JetBinaryExpression expression, @NotNull JetExpression left, @NotNull JetExpression right, @NotNull ExpressionTypingContext context) {
1060            JetExpression expr;
1061            if (JetPsiUtil.isNullConstant(left)) {
1062                expr = right;
1063            }
1064            else if (JetPsiUtil.isNullConstant(right)) {
1065                expr = left;
1066            }
1067            else return;
1068    
1069            JetSimpleNameExpression operationSign = expression.getOperationReference();
1070            JetType type = facade.getTypeInfo(expr, context).getType();
1071            if (type == null || type.isError()) return;
1072    
1073            DataFlowValue value = DataFlowValueFactory.createDataFlowValue(expr, type, context.trace.getBindingContext());
1074            Nullability nullability = context.dataFlowInfo.getNullability(value);
1075    
1076            boolean expressionIsAlways;
1077            boolean equality = operationSign.getReferencedNameElementType() == JetTokens.EQEQ || operationSign.getReferencedNameElementType() == JetTokens.EQEQEQ;
1078    
1079            if (nullability == Nullability.NULL) {
1080                expressionIsAlways = equality;
1081            }
1082            else if (nullability == Nullability.NOT_NULL) {
1083                expressionIsAlways = !equality;
1084            }
1085            else return;
1086    
1087            context.trace.report(SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways));
1088        }
1089    
1090        @NotNull
1091        private JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
1092            return assignmentIsNotAnExpressionError(expression, context);
1093        }
1094    
1095        @NotNull
1096        private JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
1097            return assignmentIsNotAnExpressionError(expression, context);
1098        }
1099    
1100        @NotNull
1101        private JetTypeInfo assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
1102            facade.checkStatementType(expression, context);
1103            context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
1104            return JetTypeInfo.create(null, context.dataFlowInfo);
1105        }
1106    
1107        @Override
1108        public JetTypeInfo visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, ExpressionTypingContext context) {
1109            JetTypeInfo typeInfo = resolveArrayAccessGetMethod(expression, context);
1110            return DataFlowUtils.checkType(typeInfo, expression, context);
1111        }
1112    
1113        @NotNull
1114        public JetTypeInfo getTypeInfoForBinaryCall(
1115                @NotNull Name name,
1116                @NotNull ExpressionTypingContext context,
1117                @NotNull JetBinaryExpression binaryExpression
1118        ) {
1119            JetExpression left = binaryExpression.getLeft();
1120            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
1121            if (left != null) {
1122                //left here is a receiver, so it doesn't depend on expected type
1123                dataFlowInfo = facade.getTypeInfo(
1124                        left, context.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
1125            }
1126            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1127    
1128            OverloadResolutionResults<FunctionDescriptor> resolutionResults;
1129            if (left != null) {
1130                ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
1131                resolutionResults = components.callResolver.resolveBinaryCall(
1132                        contextWithDataFlow.replaceScope(context.scope),
1133                        receiver, binaryExpression, name
1134                );
1135            }
1136            else {
1137                resolutionResults = OverloadResolutionResultsImpl.nameNotFound();
1138            }
1139    
1140            if (resolutionResults.isSingleResult()) {
1141                dataFlowInfo = resolutionResults.getResultingCall().getDataFlowInfoForArguments().getResultInfo();
1142            }
1143    
1144            return JetTypeInfo.create(OverloadResolutionResultsUtil.getResultingType(resolutionResults, context.contextDependency), dataFlowInfo);
1145        }
1146    
1147        @Override
1148        public JetTypeInfo visitDeclaration(@NotNull JetDeclaration dcl, ExpressionTypingContext context) {
1149            context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl));
1150            return JetTypeInfo.create(null, context.dataFlowInfo);
1151        }
1152    
1153        @Override
1154        public JetTypeInfo visitRootPackageExpression(@NotNull JetRootPackageExpression expression, ExpressionTypingContext context) {
1155            if (JetPsiUtil.isLHSOfDot(expression)) {
1156                return DataFlowUtils.checkType(JetModuleUtil.getRootPackageType(expression), expression, context, context.dataFlowInfo);
1157            }
1158            context.trace.report(PACKAGE_IS_NOT_AN_EXPRESSION.on(expression));
1159            return JetTypeInfo.create(null, context.dataFlowInfo);
1160        }
1161    
1162    
1163        @Override
1164        public JetTypeInfo visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
1165            final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
1166            final DataFlowInfo[] dataFlowInfo = new DataFlowInfo[] { context.dataFlowInfo };
1167            for (JetStringTemplateEntry entry : expression.getEntries()) {
1168                entry.accept(new JetVisitorVoid() {
1169    
1170                    @Override
1171                    public void visitStringTemplateEntryWithExpression(@NotNull JetStringTemplateEntryWithExpression entry) {
1172                        JetExpression entryExpression = entry.getExpression();
1173                        if (entryExpression != null) {
1174                            JetTypeInfo typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(dataFlowInfo[0]));
1175                            dataFlowInfo[0] = typeInfo.getDataFlowInfo();
1176                        }
1177                    }
1178    
1179                    @Override
1180                    public void visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry) {
1181                        CompileTimeConstantChecker.CharacterWithDiagnostic value = CompileTimeConstantChecker.escapedStringToCharacter(entry.getText(), entry);
1182                        Diagnostic diagnostic = value.getDiagnostic();
1183                        if (diagnostic != null) {
1184                            context.trace.report(diagnostic);
1185                        }
1186                    }
1187                });
1188            }
1189            ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, contextWithExpectedType.expectedType);
1190            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getStringType(), expression, contextWithExpectedType, dataFlowInfo[0]);
1191        }
1192    
1193        @Override
1194        public JetTypeInfo visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression, ExpressionTypingContext context) {
1195            return visitAnnotatedExpression(expression, context, false);
1196        }
1197    
1198        public JetTypeInfo visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
1199            components.expressionTypingServices.getAnnotationResolver().resolveAnnotationsWithArguments(
1200                    context.scope, expression.getAnnotationEntries(), context.trace);
1201    
1202            JetExpression baseExpression = expression.getBaseExpression();
1203            if (baseExpression == null) {
1204                return JetTypeInfo.create(null, context.dataFlowInfo);
1205            }
1206            return facade.getTypeInfo(baseExpression, context, isStatement);
1207        }
1208    
1209        @Override
1210        public JetTypeInfo visitJetElement(@NotNull JetElement element, ExpressionTypingContext context) {
1211            context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
1212            return JetTypeInfo.create(null, context.dataFlowInfo);
1213        }
1214    
1215        @NotNull
1216            /*package*/ JetTypeInfo resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) {
1217            return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
1218        }
1219    
1220        @NotNull
1221            /*package*/ JetTypeInfo resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) {
1222            return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
1223        }
1224    
1225        @NotNull
1226        private JetTypeInfo resolveArrayAccessSpecialMethod(@NotNull JetArrayAccessExpression arrayAccessExpression,
1227                                                        @Nullable JetExpression rightHandSide, //only for 'set' method
1228                                                        @NotNull ExpressionTypingContext oldContext,
1229                                                        @NotNull BindingTrace traceForResolveResult,
1230                                                        boolean isGet) {
1231            JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
1232            if (arrayExpression == null) return JetTypeInfo.create(null, oldContext.dataFlowInfo);
1233    
1234            JetTypeInfo arrayTypeInfo = facade.getTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
1235                    .replaceContextDependency(INDEPENDENT));
1236            JetType arrayType = arrayTypeInfo.getType();
1237            if (arrayType == null) {
1238                for (JetExpression indexExpression : arrayAccessExpression.getIndexExpressions()) {
1239                    facade.getTypeInfo(indexExpression, oldContext);
1240                }
1241                return arrayTypeInfo;
1242            }
1243    
1244            DataFlowInfo dataFlowInfo = arrayTypeInfo.getDataFlowInfo();
1245            ExpressionTypingContext context = oldContext.replaceDataFlowInfo(dataFlowInfo);
1246            ExpressionReceiver receiver = new ExpressionReceiver(arrayExpression, arrayType);
1247            if (!isGet) assert rightHandSide != null;
1248    
1249            OverloadResolutionResults<FunctionDescriptor> functionResults = components.callResolver.resolveCallWithGivenName(
1250                    context,
1251                    isGet
1252                    ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD)
1253                    : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD),
1254                    arrayAccessExpression,
1255                    Name.identifier(isGet ? "get" : "set")
1256            );
1257    
1258            List<JetExpression> indices = arrayAccessExpression.getIndexExpressions();
1259            // The accumulated data flow info of all index expressions is saved on the last index
1260            if (!indices.isEmpty()) {
1261                dataFlowInfo = facade.getTypeInfo(indices.get(indices.size() - 1), context).getDataFlowInfo();
1262            }
1263    
1264            if (!isGet) {
1265                dataFlowInfo = facade.getTypeInfo(rightHandSide, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
1266            }
1267    
1268            if (!functionResults.isSingleResult()) {
1269                traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression));
1270                return JetTypeInfo.create(null, dataFlowInfo);
1271            }
1272            traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall());
1273            return JetTypeInfo.create(functionResults.getResultingDescriptor().getReturnType(), dataFlowInfo);
1274        }
1275    }