001    /*
002     * Copyright 2010-2015 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.kotlin.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 com.intellij.psi.util.PsiTreeUtil;
024    import kotlin.CollectionsKt;
025    import kotlin.jvm.functions.Function0;
026    import kotlin.jvm.functions.Function1;
027    import org.jetbrains.annotations.NotNull;
028    import org.jetbrains.annotations.Nullable;
029    import org.jetbrains.kotlin.KtNodeTypes;
030    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
031    import org.jetbrains.kotlin.descriptors.*;
032    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
033    import org.jetbrains.kotlin.diagnostics.Diagnostic;
034    import org.jetbrains.kotlin.diagnostics.Errors;
035    import org.jetbrains.kotlin.lexer.KtKeywordToken;
036    import org.jetbrains.kotlin.lexer.KtTokens;
037    import org.jetbrains.kotlin.name.Name;
038    import org.jetbrains.kotlin.psi.*;
039    import org.jetbrains.kotlin.resolve.*;
040    import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
041    import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesResolutionUtilsKt;
042    import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
043    import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver;
044    import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
045    import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
046    import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
047    import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
048    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
049    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl;
050    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
051    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
052    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
053    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
054    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
055    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
056    import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability;
057    import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
058    import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
059    import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
060    import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
061    import org.jetbrains.kotlin.resolve.constants.*;
062    import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
063    import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
064    import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
065    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
066    import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
067    import org.jetbrains.kotlin.types.*;
068    import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.ResolveConstruct;
069    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
070    import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
071    import org.jetbrains.kotlin.types.expressions.unqualifiedSuper.UnqualifiedSuperKt;
072    import org.jetbrains.kotlin.util.OperatorNameConventions;
073    import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
074    
075    import java.util.Collection;
076    import java.util.Collections;
077    import java.util.Iterator;
078    import java.util.List;
079    
080    import static org.jetbrains.kotlin.diagnostics.Errors.*;
081    import static org.jetbrains.kotlin.lexer.KtTokens.*;
082    import static org.jetbrains.kotlin.resolve.BindingContext.*;
083    import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
084    import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
085    import static org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue;
086    import static org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
087    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
088    import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
089    import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
090    import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
091    import static org.jetbrains.kotlin.types.expressions.TypeReconstructionUtil.reconstructBareType;
092    
093    @SuppressWarnings("SuspiciousMethodCalls")
094    public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
095    
096        private static final TokenSet BARE_TYPES_ALLOWED = TokenSet.create(AS_KEYWORD, AS_SAFE);
097    
098        protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade) {
099            super(facade);
100        }
101    
102        private static boolean isLValueOrUnsafeReceiver(@NotNull KtSimpleNameExpression expression) {
103            PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, KtParenthesizedExpression.class);
104            if (parent instanceof KtQualifiedExpression) {
105                KtQualifiedExpression qualifiedExpression = (KtQualifiedExpression) parent;
106                // See KT-10175: receiver of unsafe call is always not-null at resolver
107                // so we have to analyze its nullability here
108                return qualifiedExpression.getOperationSign() == KtTokens.DOT &&
109                       qualifiedExpression.getReceiverExpression() == KtPsiUtil.deparenthesize(expression);
110            }
111            if (parent instanceof KtBinaryExpression) {
112                KtBinaryExpression binaryExpression = (KtBinaryExpression) parent;
113                if (!OperatorConventions.BINARY_OPERATION_NAMES.containsKey(binaryExpression.getOperationToken()) &&
114                    !KtTokens.ALL_ASSIGNMENTS.contains(binaryExpression.getOperationToken())) {
115                    return false;
116                }
117                return PsiTreeUtil.isAncestor(binaryExpression.getLeft(), expression, false);
118            }
119            return false;
120        }
121    
122        private static boolean isDangerousWithNull(@NotNull KtSimpleNameExpression expression, @NotNull ExpressionTypingContext context) {
123            PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, KtParenthesizedExpression.class);
124            if (parent instanceof KtUnaryExpression) {
125                // Unary: !! only
126                KtUnaryExpression unaryExpression = (KtUnaryExpression) parent;
127                return unaryExpression.getOperationToken() == KtTokens.EXCLEXCL;
128            }
129            if (parent instanceof KtBinaryExpressionWithTypeRHS) {
130                // Binary: unsafe as only
131                KtBinaryExpressionWithTypeRHS binaryExpression = (KtBinaryExpressionWithTypeRHS) parent;
132                KotlinType type = context.trace.get(TYPE, binaryExpression.getRight());
133                return type != null && !type.isMarkedNullable() &&
134                       binaryExpression.getOperationReference().getReferencedNameElementType() == KtTokens.AS_KEYWORD;
135            }
136            return false;
137        }
138    
139        private static void checkNull(
140                @NotNull KtSimpleNameExpression expression,
141                @NotNull ExpressionTypingContext context,
142                @Nullable KotlinType type
143        ) {
144            // Receivers are normally analyzed at resolve, with an exception of KT-10175
145            if (type != null && !type.isError() && !isLValueOrUnsafeReceiver(expression)) {
146                DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context);
147                Nullability nullability = context.dataFlowInfo.getPredictableNullability(dataFlowValue);
148                if (!nullability.canBeNonNull() && nullability.canBeNull()) {
149                    if (isDangerousWithNull(expression, context)) {
150                        context.trace.report(ALWAYS_NULL.on(expression));
151                    }
152                    else {
153                        context.trace.record(SMARTCAST_NULL, expression);
154                    }
155                }
156            }
157        }
158    
159        @Override
160        public KotlinTypeInfo visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, ExpressionTypingContext context) {
161            // TODO : other members
162            // TODO : type substitutions???
163            CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
164            KotlinTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context);
165            checkNull(expression, context, typeInfo.getType());
166    
167            return components.dataFlowAnalyzer.checkType(typeInfo, expression, context); // TODO : Extensions to this
168        }
169    
170        @Override
171        public KotlinTypeInfo visitParenthesizedExpression(@NotNull KtParenthesizedExpression expression, ExpressionTypingContext context) {
172            KtExpression innerExpression = expression.getExpression();
173            if (innerExpression == null) {
174                return TypeInfoFactoryKt.noTypeInfo(context);
175            }
176            return facade.getTypeInfo(innerExpression, context.replaceScope(context.scope));
177        }
178    
179        @Override
180        public KotlinTypeInfo visitConstantExpression(@NotNull KtConstantExpression expression, ExpressionTypingContext context) {
181            IElementType elementType = expression.getNode().getElementType();
182            if (elementType == KtNodeTypes.CHARACTER_CONSTANT
183                || elementType == KtNodeTypes.INTEGER_CONSTANT
184                || elementType == KtNodeTypes.FLOAT_CONSTANT) {
185                checkLiteralPrefixAndSuffix(expression, context);
186            }
187    
188            CompileTimeConstant<?> compileTimeConstant = components.constantExpressionEvaluator.evaluateExpression(
189                    expression, context.trace, context.expectedType
190            );
191    
192            if (!(compileTimeConstant instanceof IntegerValueTypeConstant)) {
193                CompileTimeConstantChecker constantChecker = new CompileTimeConstantChecker(context.trace, components.builtIns, false);
194                ConstantValue constantValue =
195                        compileTimeConstant != null ? ((TypedCompileTimeConstant) compileTimeConstant).getConstantValue() : null;
196                boolean hasError = constantChecker.checkConstantExpressionType(constantValue, expression, context.expectedType);
197                if (hasError) {
198                    return TypeInfoFactoryKt.createTypeInfo(getDefaultType(elementType), context);
199                }
200            }
201    
202            assert compileTimeConstant != null :
203                    "CompileTimeConstant should be evaluated for constant expression or an error should be recorded " +
204                    expression.getText();
205            return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(compileTimeConstant, expression, context);
206        }
207    
208        @NotNull
209        public KotlinType getDefaultType(IElementType constantType) {
210            KotlinBuiltIns builtIns = components.builtIns;
211            if (constantType == KtNodeTypes.INTEGER_CONSTANT) {
212                return builtIns.getIntType();
213            }
214            else if (constantType == KtNodeTypes.FLOAT_CONSTANT) {
215                return builtIns.getDoubleType();
216            }
217            else if (constantType == KtNodeTypes.BOOLEAN_CONSTANT) {
218                return builtIns.getBooleanType();
219            }
220            else if (constantType == KtNodeTypes.CHARACTER_CONSTANT) {
221                return builtIns.getCharType();
222            }
223            else if (constantType == KtNodeTypes.NULL) {
224                return builtIns.getNullableNothingType();
225            }
226            else {
227                throw new IllegalArgumentException("Unsupported constant type: " + constantType);
228            }
229        }
230    
231        @Override
232        public KotlinTypeInfo visitBinaryWithTypeRHSExpression(
233                @NotNull KtBinaryExpressionWithTypeRHS expression,
234                ExpressionTypingContext context
235        ) {
236            ExpressionTypingContext contextWithNoExpectedType =
237                    context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
238            KtExpression left = expression.getLeft();
239            KtTypeReference right = expression.getRight();
240            if (right == null) {
241                return facade.getTypeInfo(left, contextWithNoExpectedType).clearType();
242            }
243    
244            IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
245    
246            boolean allowBareTypes = BARE_TYPES_ALLOWED.contains(operationType);
247            TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, allowBareTypes);
248            PossiblyBareType possiblyBareTarget = components.typeResolver.resolvePossiblyBareType(typeResolutionContext, right);
249    
250            KotlinTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
251    
252            KotlinType subjectType = typeInfo.getType();
253            KotlinType targetType = reconstructBareType(right, possiblyBareTarget, subjectType, context.trace, components.builtIns);
254    
255            if (subjectType != null) {
256                checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, subjectType);
257                DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
258                if (operationType == AS_KEYWORD) {
259                    DataFlowValue value = createDataFlowValue(left, subjectType, context);
260                    typeInfo = typeInfo.replaceDataFlowInfo(dataFlowInfo.establishSubtyping(value, targetType));
261                }
262            }
263    
264            KotlinType result = operationType == AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
265            return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(result), expression, context);
266        }
267    
268        private void checkBinaryWithTypeRHS(
269                @NotNull KtBinaryExpressionWithTypeRHS expression,
270                @NotNull ExpressionTypingContext context,
271                @NotNull KotlinType targetType,
272                @Nullable KotlinType actualType
273        ) {
274            if (actualType == null) return;
275            KtSimpleNameExpression operationSign = expression.getOperationReference();
276            IElementType operationType = operationSign.getReferencedNameElementType();
277            if (operationType != KtTokens.AS_KEYWORD && operationType != KtTokens.AS_SAFE) {
278                context.trace.report(UNSUPPORTED.on(operationSign, "binary operation with type RHS"));
279                return;
280            }
281            checkForCastImpossibilityOrRedundancy(expression, actualType, targetType, context);
282        }
283    
284        private void checkForCastImpossibilityOrRedundancy(
285                KtBinaryExpressionWithTypeRHS expression,
286                KotlinType actualType,
287                KotlinType targetType,
288                ExpressionTypingContext context
289        ) {
290            if (actualType == null || noExpectedType(targetType) || targetType.isError()) return;
291    
292            DeclarationsCheckerKt.checkNotEnumEntry(expression.getRight(), context.trace);
293    
294            if (DynamicTypesKt.isDynamic(targetType)) {
295                KtTypeReference right = expression.getRight();
296                assert right != null : "We know target is dynamic, but RHS is missing";
297                context.trace.report(DYNAMIC_NOT_ALLOWED.on(right));
298                return;
299            }
300    
301            if (!CastDiagnosticsUtil.isCastPossible(actualType, targetType, components.platformToKotlinClassMap)) {
302                context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference()));
303                return;
304            }
305            KotlinTypeChecker typeChecker = KotlinTypeChecker.DEFAULT;
306            if (actualType.equals(targetType)) {
307                // cast to itself: String as String
308                context.trace.report(USELESS_CAST.on(expression));
309                return;
310            }
311            Collection<KotlinType> possibleTypes = components.dataFlowAnalyzer.getAllPossibleTypes(
312                    expression.getLeft(), context.dataFlowInfo, actualType, context);
313    
314            boolean checkExactType = checkExactTypeForUselessCast(expression);
315            for (KotlinType possibleType : possibleTypes) {
316                boolean castIsUseless = checkExactType
317                                        ? possibleType.equals(targetType)
318                                        : typeChecker.isSubtypeOf(possibleType, targetType);
319                if (castIsUseless) {
320                    context.trace.report(USELESS_CAST.on(expression));
321                    return;
322                }
323            }
324            if (CastDiagnosticsUtil.isCastErased(actualType, targetType, typeChecker)) {
325                context.trace.report(UNCHECKED_CAST.on(expression, actualType, targetType));
326            }
327        }
328    
329        // Casting an argument or a receiver to a supertype may be useful to select an exact overload of a method.
330        // Casting to a supertype in other contexts is unlikely to be useful.
331        private static boolean checkExactTypeForUselessCast(KtBinaryExpressionWithTypeRHS expression) {
332            PsiElement parent = expression.getParent();
333            while (parent instanceof KtParenthesizedExpression ||
334                   parent instanceof KtLabeledExpression ||
335                   parent instanceof KtAnnotatedExpression) {
336                parent = parent.getParent();
337            }
338            if (parent instanceof KtValueArgument) {
339                return true;
340            }
341            if (parent instanceof KtQualifiedExpression) {
342                KtExpression receiver = ((KtQualifiedExpression) parent).getReceiverExpression();
343                return PsiTreeUtil.isAncestor(receiver, expression, false);
344            }
345            return false;
346        }
347    
348        @Override
349        public KotlinTypeInfo visitThisExpression(@NotNull KtThisExpression expression, ExpressionTypingContext context) {
350            KotlinType result = null;
351            LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, false);
352    
353            switch (resolutionResult.getCode()) {
354                case LABEL_RESOLUTION_ERROR:
355                    // Do nothing, the error is already reported
356                    break;
357                case NO_THIS:
358                    context.trace.report(NO_THIS.on(expression));
359                    break;
360                case SUCCESS:
361                    result = resolutionResult.getReceiverParameterDescriptor().getType();
362                    context.trace.recordType(expression.getInstanceReference(), result);
363                    break;
364            }
365            return components.dataFlowAnalyzer.createCheckedTypeInfo(result, context, expression);
366        }
367    
368        @Override
369        public KotlinTypeInfo visitSuperExpression(@NotNull KtSuperExpression expression, ExpressionTypingContext context) {
370            LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, true);
371    
372            if (!KtPsiUtil.isLHSOfDot(expression)) {
373                context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText()));
374                return errorInSuper(expression, context);
375            }
376    
377            switch (resolutionResult.getCode()) {
378                case LABEL_RESOLUTION_ERROR:
379                    // The error is already reported
380                    return errorInSuper(expression, context);
381                case NO_THIS:
382                    context.trace.report(SUPER_NOT_AVAILABLE.on(expression));
383                    return errorInSuper(expression, context);
384                case SUCCESS:
385                    KotlinType result = checkPossiblyQualifiedSuper(expression, context, resolutionResult.getReceiverParameterDescriptor());
386                    if (result != null) {
387                        context.trace.recordType(expression.getInstanceReference(), result);
388                    }
389                    return components.dataFlowAnalyzer.createCheckedTypeInfo(result, context, expression);
390            }
391            throw new IllegalStateException("Unknown code: " + resolutionResult.getCode());
392        }
393    
394        private KotlinTypeInfo errorInSuper(KtSuperExpression expression, ExpressionTypingContext context) {
395            KtTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
396            if (superTypeQualifier != null) {
397                components.typeResolver.resolveType(context.scope, superTypeQualifier, context.trace, true);
398            }
399            return TypeInfoFactoryKt.noTypeInfo(context);
400        }
401    
402        private KotlinType checkPossiblyQualifiedSuper(
403                KtSuperExpression expression,
404                ExpressionTypingContext context,
405                ReceiverParameterDescriptor thisReceiver
406        ) {
407            KotlinType result = null;
408            KotlinType thisType = thisReceiver.getType();
409            Collection<KotlinType> supertypes = thisType.getConstructor().getSupertypes();
410            TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
411    
412            KtTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
413            if (superTypeQualifier != null) {
414                KtTypeElement typeElement = superTypeQualifier.getTypeElement();
415    
416                DeclarationDescriptor classifierCandidate = null;
417                KotlinType supertype = null;
418                PsiElement redundantTypeArguments = null;
419                if (typeElement instanceof KtUserType) {
420                    KtUserType userType = (KtUserType) typeElement;
421                    // This may be just a superclass name even if the superclass is generic
422                    if (userType.getTypeArguments().isEmpty()) {
423                        classifierCandidate = components.typeResolver.resolveClass(context.scope, userType, context.trace);
424                    }
425                    else {
426                        supertype = components.typeResolver.resolveType(context.scope, superTypeQualifier, context.trace, true);
427                        redundantTypeArguments = userType.getTypeArgumentList();
428                    }
429                }
430                else {
431                    supertype = components.typeResolver.resolveType(context.scope, superTypeQualifier, context.trace, true);
432                }
433    
434                if (supertype != null) {
435                    if (supertypes.contains(supertype)) {
436                        result = supertype;
437                    }
438                }
439                else if (classifierCandidate instanceof ClassDescriptor) {
440                    ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
441    
442                    for (KotlinType declaredSupertype : supertypes) {
443                        if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
444                            result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
445                            break;
446                        }
447                    }
448                }
449    
450                boolean validClassifier = classifierCandidate != null && !ErrorUtils.isError(classifierCandidate);
451                boolean validType = supertype != null && !supertype.isError();
452                if (result == null && (validClassifier || validType)) {
453                    context.trace.report(NOT_A_SUPERTYPE.on(superTypeQualifier));
454                }
455                else if (redundantTypeArguments != null) {
456                    context.trace.report(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER.on(redundantTypeArguments));
457                }
458            }
459            else {
460                if (UnqualifiedSuperKt.isPossiblyAmbiguousUnqualifiedSuper(expression, supertypes)) {
461                    Collection<KotlinType> supertypesResolvedFromContext =
462                            UnqualifiedSuperKt.resolveUnqualifiedSuperFromExpressionContext(
463                                    expression, supertypes, components.builtIns.getAnyType());
464                    if (supertypesResolvedFromContext.size() == 1) {
465                        KotlinType singleResolvedType = supertypesResolvedFromContext.iterator().next();
466                        result = substitutor.substitute(singleResolvedType, Variance.INVARIANT);
467                    }
468                    else if (supertypesResolvedFromContext.isEmpty()) {
469                        // No supertype found, either with concrete or abstract members.
470                        // Resolve to 'Any' (this will cause diagnostics for unresolved member reference).
471                        result = components.builtIns.getAnyType();
472                    }
473                    else {
474                        context.trace.report(AMBIGUOUS_SUPER.on(expression));
475                    }
476                }
477                else {
478                    // supertypes may be empty when all the supertypes are error types (are not resolved, for example)
479                    KotlinType type = supertypes.isEmpty()
480                                      ? components.builtIns.getAnyType()
481                                      : supertypes.iterator().next();
482                    result = substitutor.substitute(type, Variance.INVARIANT);
483                }
484            }
485            if (result != null) {
486                if (DescriptorUtils.isInterface(thisType.getConstructor().getDeclarationDescriptor())) {
487                    if (DescriptorUtils.isClass(result.getConstructor().getDeclarationDescriptor())) {
488                        context.trace.report(SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE.on(expression));
489                    }
490                }
491                context.trace.recordType(expression.getInstanceReference(), result);
492                context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(),
493                                     result.getConstructor().getDeclarationDescriptor());
494            }
495    
496            BindingContextUtilsKt.recordScope(context.trace, context.scope, superTypeQualifier);
497            return result;
498        }
499    
500        @NotNull // No class receivers
501        private LabelResolver.LabeledReceiverResolutionResult resolveToReceiver(
502                KtInstanceExpressionWithLabel expression,
503                ExpressionTypingContext context,
504                boolean onlyClassReceivers
505        ) {
506            Name labelName = expression.getLabelNameAsName();
507            if (labelName != null) {
508                LabelResolver.LabeledReceiverResolutionResult resolutionResult =
509                        LabelResolver.INSTANCE.resolveThisOrSuperLabel(expression, context, labelName);
510                if (resolutionResult.success()) {
511                    ReceiverParameterDescriptor receiverParameterDescriptor = resolutionResult.getReceiverParameterDescriptor();
512                    recordThisOrSuperCallInTraceAndCallExtension(context, receiverParameterDescriptor, expression);
513                    if (onlyClassReceivers && !isDeclaredInClass(receiverParameterDescriptor)) {
514                        return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(null);
515                    }
516                }
517                return resolutionResult;
518            }
519            else {
520                ReceiverParameterDescriptor result = null;
521                List<ReceiverParameterDescriptor> receivers = ScopeUtilsKt.getImplicitReceiversHierarchy(context.scope);
522                if (onlyClassReceivers) {
523                    for (ReceiverParameterDescriptor receiver : receivers) {
524                        if (isDeclaredInClass(receiver)) {
525                            result = receiver;
526                            break;
527                        }
528                    }
529                }
530                else if (!receivers.isEmpty()) {
531                    result = receivers.get(0);
532                }
533                if (result != null) {
534                    context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration());
535                    recordThisOrSuperCallInTraceAndCallExtension(context, result, expression);
536                }
537                return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result);
538            }
539        }
540    
541        private void recordThisOrSuperCallInTraceAndCallExtension(
542                ExpressionTypingContext context,
543                ReceiverParameterDescriptor descriptor,
544                KtExpression expression
545        ) {
546            BindingTrace trace = context.trace;
547            Call call = CallMaker.makeCall(expression, NO_RECEIVER, null, expression, Collections.<ValueArgument>emptyList());
548            ResolutionCandidate<ReceiverParameterDescriptor> resolutionCandidate =
549                    ResolutionCandidate.create(
550                            call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null);
551    
552            ResolvedCallImpl<ReceiverParameterDescriptor> resolvedCall =
553                    ResolvedCallImpl.create(resolutionCandidate,
554                                            TemporaryBindingTrace.create(trace, "Fake trace for fake 'this' or 'super' resolved call"),
555                                            TracingStrategy.EMPTY,
556                                            new DataFlowInfoForArgumentsImpl(call));
557            resolvedCall.markCallAsCompleted();
558    
559            trace.record(RESOLVED_CALL, call, resolvedCall);
560            trace.record(CALL, expression, call);
561    
562            BasicCallResolutionContext resolutionContext =
563                    BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE);
564            resolutionContext.performContextDependentCallChecks(resolvedCall);
565            for (CallChecker checker : components.callCheckers) {
566                checker.check(resolvedCall, resolutionContext);
567            }
568    
569            components.symbolUsageValidator.validateCall(resolvedCall, descriptor, trace, expression);
570        }
571    
572        private static boolean isDeclaredInClass(ReceiverParameterDescriptor receiver) {
573            return receiver.getContainingDeclaration() instanceof ClassDescriptor;
574        }
575    
576        @Override
577        public KotlinTypeInfo visitBlockExpression(@NotNull KtBlockExpression expression, ExpressionTypingContext context) {
578            return components.expressionTypingServices.getBlockReturnedType(expression, context, false);
579        }
580    
581        @Override
582        public KotlinTypeInfo visitClassLiteralExpression(@NotNull KtClassLiteralExpression expression, ExpressionTypingContext c) {
583            KotlinType type = resolveClassLiteral(expression, c);
584            if (type != null && !type.isError()) {
585                return components.dataFlowAnalyzer.createCheckedTypeInfo(
586                        components.reflectionTypes.getKClassType(Annotations.Companion.getEMPTY(), type), c, expression
587                );
588            }
589    
590            return TypeInfoFactoryKt.createTypeInfo(ErrorUtils.createErrorType("Unresolved class"), c);
591        }
592    
593        @Nullable
594        private KotlinType resolveClassLiteral(@NotNull KtClassLiteralExpression expression, ExpressionTypingContext c) {
595            KtTypeReference typeReference = expression.getTypeReference();
596    
597            if (typeReference == null) {
598                // "::class" will mean "this::class", a class of "this" instance
599                c.trace.report(UNSUPPORTED.on(expression, "Class literals with empty left hand side are not yet supported"));
600                return null;
601            }
602    
603            TypeResolutionContext context =
604                    new TypeResolutionContext(c.scope, c.trace, /* checkBounds = */ false, /* allowBareTypes = */ true);
605            PossiblyBareType possiblyBareType =
606                    components.typeResolver.resolvePossiblyBareType(context, typeReference);
607    
608            KotlinType type = null;
609            if (possiblyBareType.isBare()) {
610                if (!possiblyBareType.isNullable()) {
611                    ClassifierDescriptor descriptor = possiblyBareType.getBareTypeConstructor().getDeclarationDescriptor();
612                    if (descriptor instanceof ClassDescriptor) {
613                        ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
614                        if (KotlinBuiltIns.isNonPrimitiveArray(classDescriptor)) {
615                            context.trace.report(ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT.on(expression));
616                            return null;
617                        }
618                        type = substituteWithStarProjections(classDescriptor);
619                    }
620                }
621            }
622            else {
623                KotlinType actualType = possiblyBareType.getActualType();
624                if (actualType.isError()) return null;
625                if (isAllowedInClassLiteral(actualType)) {
626                    type = actualType;
627                }
628            }
629    
630            if (type != null) {
631                return type;
632            }
633    
634            context.trace.report(CLASS_LITERAL_LHS_NOT_A_CLASS.on(expression));
635            return null;
636        }
637    
638        @NotNull
639        private static KotlinType substituteWithStarProjections(@NotNull ClassDescriptor descriptor) {
640            TypeConstructor typeConstructor = descriptor.getTypeConstructor();
641            List<TypeProjection> arguments =
642                    CollectionsKt.map(typeConstructor.getParameters(), new Function1<TypeParameterDescriptor, TypeProjection>() {
643                        @Override
644                        public TypeProjection invoke(TypeParameterDescriptor descriptor) {
645                            return TypeUtils.makeStarProjection(descriptor);
646                        }
647                    });
648    
649            return KotlinTypeImpl.create(Annotations.Companion.getEMPTY(), descriptor, false, arguments);
650        }
651    
652        private static boolean isAllowedInClassLiteral(@NotNull KotlinType type) {
653            return isClassAvailableAtRuntime(type, false);
654        }
655    
656        private static boolean isClassAvailableAtRuntime(@NotNull KotlinType type, boolean canBeNullable) {
657            if (type.isMarkedNullable() && !canBeNullable) return false;
658    
659            TypeConstructor typeConstructor = type.getConstructor();
660            ClassifierDescriptor typeDeclarationDescriptor = typeConstructor.getDeclarationDescriptor();
661            boolean typeIsArray = KotlinBuiltIns.isArray(type);
662    
663            if (typeDeclarationDescriptor instanceof ClassDescriptor) {
664                List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
665                if (parameters.size() != type.getArguments().size()) return false;
666    
667                Iterator<TypeProjection> typeArgumentsIterator = type.getArguments().iterator();
668                for (TypeParameterDescriptor parameter : parameters) {
669                    if (!typeIsArray && !parameter.isReified()) return false;
670    
671                    TypeProjection typeArgument = typeArgumentsIterator.next();
672    
673                    if (typeArgument == null) return false;
674                    if (typeArgument.isStarProjection()) return false;
675                    if (!isClassAvailableAtRuntime(typeArgument.getType(), true)) return false;
676                }
677    
678                return true;
679            }
680            else if (typeDeclarationDescriptor instanceof TypeParameterDescriptor) {
681                return ((TypeParameterDescriptor) typeDeclarationDescriptor).isReified();
682            }
683    
684            return false;
685        }
686    
687        @Override
688        public KotlinTypeInfo visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, ExpressionTypingContext c) {
689            KtTypeReference typeReference = expression.getTypeReference();
690    
691            KotlinType receiverType =
692                    typeReference == null
693                    ? null
694                    : components.typeResolver.resolveType(c.scope, typeReference, c.trace, false);
695    
696            KtSimpleNameExpression callableReference = expression.getCallableReference();
697            if (callableReference.getReferencedName().isEmpty()) {
698                c.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference));
699                KotlinType errorType = ErrorUtils.createErrorType("Empty callable reference");
700                return components.dataFlowAnalyzer.createCheckedTypeInfo(errorType, c, expression);
701            }
702    
703            KotlinType result = getCallableReferenceType(expression, receiverType, c);
704            return components.dataFlowAnalyzer.createCheckedTypeInfo(result, c, expression);
705        }
706    
707        @Override
708        public KotlinTypeInfo visitObjectLiteralExpression(
709                @NotNull final KtObjectLiteralExpression expression,
710                final ExpressionTypingContext context
711        ) {
712            final KotlinType[] result = new KotlinType[1];
713            TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace,
714                                                                                "trace to resolve object literal expression", expression);
715            ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor> handler =
716                    new ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor>() {
717    
718                        @Override
719                        public void handleRecord(
720                                WritableSlice<PsiElement, ClassDescriptor> slice,
721                                PsiElement declaration,
722                                final ClassDescriptor descriptor
723                        ) {
724                            if (slice == CLASS && declaration == expression.getObjectDeclaration()) {
725                                KotlinType defaultType = DeferredType.createRecursionIntolerant(components.globalContext.getStorageManager(),
726                                                                                                context.trace,
727                                                                                                new Function0<KotlinType>() {
728                                                                                                    @Override
729                                                                                                    public KotlinType invoke() {
730                                                                                                        return descriptor.getDefaultType();
731                                                                                                    }
732                                                                                                });
733                                result[0] = defaultType;
734                            }
735                        }
736                    };
737            ObservableBindingTrace traceAdapter = new ObservableBindingTrace(temporaryTrace);
738            traceAdapter.addHandler(CLASS, handler);
739            components.localClassifierAnalyzer.processClassOrObject(null, // don't need to add classifier of object literal to any scope
740                                                                    context.replaceBindingTrace(traceAdapter)
741                                                                           .replaceContextDependency(INDEPENDENT),
742                                                                    context.scope.getOwnerDescriptor(),
743                                                                    expression.getObjectDeclaration());
744            temporaryTrace.commit();
745            DataFlowInfo resultFlowInfo = context.dataFlowInfo;
746            for (KtDelegationSpecifier specifier : expression.getObjectDeclaration().getDelegationSpecifiers()) {
747                if (specifier instanceof KtDelegatorToSuperCall) {
748                    KtDelegatorToSuperCall delegator = (KtDelegatorToSuperCall) specifier;
749                    KotlinTypeInfo delegatorTypeInfo = context.trace.get(EXPRESSION_TYPE_INFO, delegator.getCalleeExpression());
750                    if (delegatorTypeInfo != null) {
751                        resultFlowInfo = resultFlowInfo.and(delegatorTypeInfo.getDataFlowInfo());
752                    }
753                }
754            }
755            // Breaks are not possible inside constructor arguments, so jumpPossible or jumpFlowInfo are not necessary here
756            KotlinTypeInfo resultTypeInfo = components.dataFlowAnalyzer.checkType(TypeInfoFactoryKt.createTypeInfo(result[0], resultFlowInfo),
757                                                                                  expression,
758                                                                                  context);
759            // We have to record it here,
760            // otherwise ExpressionTypingVisitorDispatcher records wrong information
761            context.trace.record(EXPRESSION_TYPE_INFO, expression, resultTypeInfo);
762            context.trace.record(PROCESSED, expression);
763            return resultTypeInfo;
764        }
765    
766        @Nullable
767        private KotlinType getCallableReferenceType(
768                @NotNull KtCallableReferenceExpression expression,
769                @Nullable KotlinType lhsType,
770                @NotNull ExpressionTypingContext context
771        ) {
772            KtSimpleNameExpression reference = expression.getCallableReference();
773    
774            boolean[] resolved = new boolean[1];
775            CallableDescriptor descriptor = CallableReferencesResolutionUtilsKt.resolveCallableReferenceTarget(
776                    expression, lhsType, context, resolved, components.callResolver);
777            if (!resolved[0]) {
778                context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
779            }
780            if (descriptor == null) return null;
781    
782            if (expression.getTypeReference() == null &&
783                (descriptor.getDispatchReceiverParameter() != null || descriptor.getExtensionReceiverParameter() != null)) {
784                context.trace.report(CALLABLE_REFERENCE_TO_MEMBER_OR_EXTENSION_WITH_EMPTY_LHS.on(reference));
785            }
786    
787            DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
788            if (DescriptorUtils.isObject(containingDeclaration)) {
789                context.trace.report(CALLABLE_REFERENCE_TO_OBJECT_MEMBER.on(reference));
790            }
791            if (descriptor instanceof ConstructorDescriptor && DescriptorUtils.isAnnotationClass(containingDeclaration)) {
792                context.trace.report(CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR.on(reference));
793            }
794    
795            return CallableReferencesResolutionUtilsKt.createReflectionTypeForResolvedCallableReference(
796                    expression, lhsType, descriptor, context, components.reflectionTypes
797            );
798        }
799    
800        @Override
801        public KotlinTypeInfo visitQualifiedExpression(@NotNull KtQualifiedExpression expression, ExpressionTypingContext context) {
802            CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
803            return callExpressionResolver.getQualifiedExpressionTypeInfo(expression, context);
804        }
805    
806        @Override
807        public KotlinTypeInfo visitCallExpression(@NotNull KtCallExpression expression, ExpressionTypingContext context) {
808            CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
809            return callExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context);
810        }
811    
812        @Override
813        public KotlinTypeInfo visitUnaryExpression(@NotNull KtUnaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
814            ExpressionTypingContext context = isUnaryExpressionDependentOnExpectedType(expression)
815                                              ? contextWithExpectedType
816                                              : contextWithExpectedType.replaceContextDependency(INDEPENDENT)
817                                                                       .replaceExpectedType(NO_EXPECTED_TYPE);
818    
819            KtExpression baseExpression = expression.getBaseExpression();
820            if (baseExpression == null) return TypeInfoFactoryKt.noTypeInfo(context);
821    
822            KtSimpleNameExpression operationSign = expression.getOperationReference();
823    
824            IElementType operationType = operationSign.getReferencedNameElementType();
825    
826            // Special case for expr!!
827            if (operationType == KtTokens.EXCLEXCL) {
828                return visitExclExclExpression(expression, context);
829            }
830    
831            // Type check the base expression
832            KotlinTypeInfo typeInfo = facade.safeGetTypeInfo(baseExpression, context);
833            KotlinType type = ExpressionTypingUtils.safeGetType(typeInfo);
834            ExpressionReceiver receiver = ExpressionReceiver.Companion.create(baseExpression, type, context.trace.getBindingContext());
835    
836            Call call = CallMaker.makeCall(receiver, expression);
837    
838            // Conventions for unary operations
839            Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
840            if (name == null) {
841                context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
842                return typeInfo.clearType();
843            }
844    
845            // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
846            if ((operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) &&
847                baseExpression instanceof KtArrayAccessExpression) {
848                KtExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(
849                        baseExpression.getProject(), context.trace, "e", type);
850                TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(
851                        context.trace, "trace to resolve array access set method for unary expression", expression);
852                ExpressionTypingContext newContext = context.replaceBindingTrace(temporaryBindingTrace);
853                resolveArrayAccessSetMethod((KtArrayAccessExpression) baseExpression, stubExpression, newContext, context.trace);
854            }
855    
856            // Resolve the operation reference
857            OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(
858                    context, call, expression.getOperationReference(), name);
859    
860            if (!resolutionResults.isSuccess()) {
861                return typeInfo.clearType();
862            }
863    
864            // Computing the return type
865            KotlinType returnType = resolutionResults.getResultingDescriptor().getReturnType();
866            KotlinType result;
867            if (operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) {
868                assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
869                if (KotlinBuiltIns.isUnit(returnType)) {
870                    result = ErrorUtils.createErrorType(components.builtIns.getUnit().getName().asString());
871                    context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
872                }
873                else {
874                    KotlinType receiverType = receiver.getType();
875                    if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, receiverType)) {
876                        context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
877                    }
878                    else {
879                        context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
880                        KtExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(
881                                baseExpression.getProject(), context.trace, "e", type);
882                        checkLValue(context.trace, context, baseExpression, stubExpression);
883                    }
884                    // x++ type is x type, but ++x type is x.inc() type
885                    DataFlowValue receiverValue = DataFlowValueFactory.createDataFlowValue(
886                            (ReceiverValue) call.getExplicitReceiver(), contextWithExpectedType);
887                    if (expression instanceof KtPrefixExpression) {
888                        result = returnType;
889                    }
890                    else {
891                        result = receiverType;
892                        // Also record data flow information for x++ value (= x)
893                        DataFlowValue returnValue = DataFlowValueFactory.createDataFlowValue(expression, receiverType, contextWithExpectedType);
894                        typeInfo = typeInfo.replaceDataFlowInfo(typeInfo.getDataFlowInfo().assign(returnValue, receiverValue));
895                    }
896                }
897            }
898            else {
899                result = returnType;
900            }
901    
902            CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(
903                    expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
904            );
905            if (value != null) {
906                return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
907            }
908    
909            return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(result),
910                                                         expression,
911                                                         contextWithExpectedType.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
912        }
913    
914        private KotlinTypeInfo visitExclExclExpression(@NotNull KtUnaryExpression expression, @NotNull ExpressionTypingContext context) {
915            KtExpression baseExpression = expression.getBaseExpression();
916            assert baseExpression != null;
917            KtSimpleNameExpression operationSign = expression.getOperationReference();
918            assert operationSign.getReferencedNameElementType() == KtTokens.EXCLEXCL;
919    
920            // TODO: something must be done for not to lose safe call chain information here
921            // See also CallExpressionResolver.getSimpleNameExpressionTypeInfo, .getQualifiedExpressionTypeInfo
922            Call call = createCallForSpecialConstruction(
923                    expression, expression.getOperationReference(), Collections.singletonList(baseExpression));
924            components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
925                    call, ResolveConstruct.EXCL_EXCL, Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null);
926            KotlinTypeInfo baseTypeInfo = BindingContextUtils.getRecordedTypeInfo(baseExpression, context.trace.getBindingContext());
927    
928            if (ArgumentTypeResolver.isFunctionLiteralArgument(baseExpression, context)) {
929                context.trace.report(NOT_NULL_ASSERTION_ON_FUNCTION_LITERAL.on(operationSign));
930                return baseTypeInfo;
931            }
932            assert baseTypeInfo != null : "Base expression was not processed: " + expression;
933            KotlinType baseType = baseTypeInfo.getType();
934            if (baseType == null) {
935                return baseTypeInfo;
936            }
937            DataFlowInfo dataFlowInfo = baseTypeInfo.getDataFlowInfo();
938            if (isKnownToBeNotNull(baseExpression, context) && !baseType.isError()) {
939                context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, baseType));
940            }
941            else {
942                DataFlowValue value = createDataFlowValue(baseExpression, baseType, context);
943                baseTypeInfo = baseTypeInfo.replaceDataFlowInfo(dataFlowInfo.disequate(value, DataFlowValue.nullValue(components.builtIns)));
944            }
945            KotlinType resultingType = TypeUtils.makeNotNullable(baseType);
946            if (context.contextDependency == DEPENDENT) {
947                return baseTypeInfo.replaceType(resultingType);
948            }
949    
950            // The call to checkType() is only needed here to execute additionalTypeCheckers, hence the NO_EXPECTED_TYPE
951            return components.dataFlowAnalyzer.checkType(
952                    baseTypeInfo.replaceType(resultingType), expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
953        }
954    
955        @Override
956        public KotlinTypeInfo visitLabeledExpression(
957                @NotNull KtLabeledExpression expression, ExpressionTypingContext context
958        ) {
959            return visitLabeledExpression(expression, context, false);
960        }
961    
962        @NotNull
963        public KotlinTypeInfo visitLabeledExpression(
964                @NotNull KtLabeledExpression expression,
965                @NotNull ExpressionTypingContext context,
966                boolean isStatement
967        ) {
968            KtSimpleNameExpression labelExpression = expression.getTargetLabel();
969            if (labelExpression != null) {
970                PsiElement labelIdentifier = labelExpression.getIdentifier();
971                UnderscoreChecker.INSTANCE$.checkIdentifier(labelIdentifier, context.trace);
972            }
973            KtExpression baseExpression = expression.getBaseExpression();
974            if (baseExpression == null) return TypeInfoFactoryKt.noTypeInfo(context);
975    
976            return facade.getTypeInfo(baseExpression, context, isStatement);
977        }
978    
979        private static boolean isKnownToBeNotNull(KtExpression expression, ExpressionTypingContext context) {
980            KotlinType type = context.trace.getType(expression);
981            assert type != null : "This method is only supposed to be called when the type is not null";
982            return isKnownToBeNotNull(expression, type, context);
983        }
984    
985        private static boolean isKnownToBeNotNull(KtExpression expression, KotlinType jetType, ExpressionTypingContext context) {
986            DataFlowValue dataFlowValue = createDataFlowValue(expression, jetType, context);
987            return !context.dataFlowInfo.getPredictableNullability(dataFlowValue).canBeNull();
988        }
989    
990        /**
991         * @return {@code true} iff expression can be assigned to
992         */
993        public boolean checkLValue(
994                @NotNull BindingTrace trace,
995                @NotNull ExpressionTypingContext context,
996                @NotNull KtExpression expression,
997                @Nullable KtExpression rightHandSide
998        ) {
999            return checkLValue(trace, context, expression, rightHandSide, false);
1000        }
1001    
1002        private boolean checkLValue(
1003                @NotNull BindingTrace trace,
1004                @NotNull ExpressionTypingContext context,
1005                @NotNull KtExpression expressionWithParenthesis,
1006                @Nullable KtExpression rightHandSide,
1007                boolean canBeThis
1008        ) {
1009            KtExpression expression = KtPsiUtil.deparenthesize(expressionWithParenthesis);
1010            if (expression instanceof KtArrayAccessExpression) {
1011                KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) expression;
1012                KtExpression arrayExpression = arrayAccessExpression.getArrayExpression();
1013                if (arrayExpression == null || rightHandSide == null) return false;
1014    
1015                TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(trace, "Trace for checking set function");
1016                ExpressionTypingContext findSetterContext = context.replaceBindingTrace(ignoreReportsTrace);
1017                KotlinTypeInfo info = resolveArrayAccessSetMethod(arrayAccessExpression, rightHandSide, findSetterContext, ignoreReportsTrace);
1018                return info.getType() != null;
1019            }
1020    
1021            if (canBeThis && expression instanceof KtThisExpression) return true;
1022            VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
1023    
1024            boolean result = true;
1025            KtExpression reportOn = expression != null ? expression : expressionWithParenthesis;
1026            if (reportOn instanceof KtQualifiedExpression) {
1027                KtExpression selector = ((KtQualifiedExpression) reportOn).getSelectorExpression();
1028                if (selector != null)
1029                    reportOn = selector;
1030            }
1031    
1032            if (variable instanceof PropertyDescriptor) {
1033                PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
1034                PropertySetterDescriptor setter = propertyDescriptor.getSetter();
1035                if (propertyDescriptor.isSetterProjectedOut()) {
1036                    trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
1037                    result = false;
1038                }
1039                else {
1040                    if (setter != null) {
1041                        components.symbolUsageValidator.validateCall(null, setter, trace, reportOn);
1042                    }
1043                }
1044            }
1045    
1046            if (variable == null) {
1047                trace.report(VARIABLE_EXPECTED.on(reportOn));
1048                result = false;
1049            }
1050            else if (!variable.isVar()) {
1051                result = false;
1052            }
1053    
1054            return result;
1055        }
1056    
1057        @Override
1058        public KotlinTypeInfo visitBinaryExpression(@NotNull KtBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
1059            ExpressionTypingContext context = isBinaryExpressionDependentOnExpectedType(expression)
1060                                              ? contextWithExpectedType
1061                                              : contextWithExpectedType.replaceContextDependency(INDEPENDENT)
1062                                                                       .replaceExpectedType(NO_EXPECTED_TYPE);
1063    
1064            KtSimpleNameExpression operationSign = expression.getOperationReference();
1065            KtExpression left = expression.getLeft();
1066            KtExpression right = expression.getRight();
1067            IElementType operationType = operationSign.getReferencedNameElementType();
1068    
1069            KotlinTypeInfo result;
1070    
1071            //Expressions that can depend on expected type
1072            if (operationType == KtTokens.IDENTIFIER) {
1073                Name referencedName = operationSign.getReferencedNameAsName();
1074                result = getTypeInfoForBinaryCall(referencedName, context, expression);
1075            }
1076            else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) {
1077                Name referencedName = OperatorConventions.BINARY_OPERATION_NAMES.get(operationType);
1078                result = getTypeInfoForBinaryCall(referencedName, context, expression);
1079            }
1080            else if (operationType == KtTokens.ELVIS) {
1081                //base expression of elvis operator is checked for 'type mismatch', so the whole expression shouldn't be checked
1082                return visitElvisExpression(expression, context);
1083            }
1084    
1085            //Expressions that don't depend on expected type
1086            else if (operationType == KtTokens.EQ) {
1087                result = visitAssignment(expression, context);
1088            }
1089            else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
1090                result = visitAssignmentOperation(expression, context);
1091            }
1092            else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
1093                result = visitComparison(expression, context, operationSign);
1094            }
1095            else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
1096                result = visitEquality(expression, context, operationSign, left, right);
1097            }
1098            else if (OperatorConventions.IDENTITY_EQUALS_OPERATIONS.contains(operationType)) {
1099                context.trace.record(REFERENCE_TARGET, operationSign, components.builtIns.getIdentityEquals());
1100                ensureNonemptyIntersectionOfOperandTypes(expression, context);
1101                // TODO : Check comparison pointlessness
1102                result = TypeInfoFactoryKt.createTypeInfo(components.builtIns.getBooleanType(), context);
1103            }
1104            else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
1105                ValueArgument leftArgument = CallMaker.makeValueArgument(left, left != null ? left : operationSign);
1106                result = checkInExpression(expression, operationSign, leftArgument, right, context);
1107            }
1108            else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
1109                result = visitBooleanOperationExpression(operationType, left, right, context);
1110            }
1111            else {
1112                context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
1113                result = TypeInfoFactoryKt.noTypeInfo(context);
1114            }
1115            CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(
1116                    expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
1117            );
1118            if (value != null) {
1119                return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
1120            }
1121            return components.dataFlowAnalyzer.checkType(result, expression, contextWithExpectedType);
1122        }
1123    
1124        private KotlinTypeInfo visitEquality(
1125                KtBinaryExpression expression,
1126                ExpressionTypingContext context,
1127                KtSimpleNameExpression operationSign,
1128                final KtExpression left,
1129                final KtExpression right
1130        ) {
1131            if (right == null || left == null) {
1132                ExpressionTypingUtils.getTypeInfoOrNullType(right, context, facade);
1133                ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
1134                return TypeInfoFactoryKt.createTypeInfo(components.builtIns.getBooleanType(), context);
1135            }
1136    
1137            KotlinTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
1138    
1139            DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
1140            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1141    
1142            KotlinTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithDataFlow);
1143    
1144            TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create(
1145                    context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
1146            traceInterpretingRightAsNullableAny.recordType(right, components.builtIns.getNullableAnyType());
1147    
1148            // Nothing? has no members, and `equals()` would be unresolved on it
1149            KotlinType leftType = leftTypeInfo.getType();
1150            if (leftType != null && KotlinBuiltIns.isNothingOrNullableNothing(leftType)) {
1151                traceInterpretingRightAsNullableAny.recordType(left, components.builtIns.getNullableAnyType());
1152            }
1153    
1154            ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
1155            ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, newContext);
1156            Call call = CallMaker.makeCallWithExpressions(
1157                    expression,
1158                    receiver,
1159                    // semantically, a call to `==` is a safe call
1160                    new KtPsiFactory(expression.getProject()).createSafeCallNode(),
1161                    operationSign,
1162                    Collections.singletonList(right)
1163            );
1164            OverloadResolutionResults<FunctionDescriptor> resolutionResults =
1165                    components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorNameConventions.EQUALS);
1166    
1167            traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() {
1168                @Override
1169                public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
1170                    // the type of the right (and sometimes left) expression isn't 'Any?' actually
1171                    if ((key == right || key == left) && slice == EXPRESSION_TYPE_INFO) return false;
1172    
1173                    // a hack due to KT-678
1174                    // without this line an smartcast is reported on the receiver (if it was previously checked for not-null)
1175                    // with not-null check the resolution result changes from 'fun Any?.equals' to 'equals' member
1176                    if (key == left && slice == SMARTCAST) return false;
1177    
1178                    return true;
1179                }
1180            }, true);
1181    
1182            if (resolutionResults.isSuccess()) {
1183                FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
1184                if (ensureBooleanResult(operationSign, OperatorNameConventions.EQUALS, equals.getReturnType(), context)) {
1185                    ensureNonemptyIntersectionOfOperandTypes(expression, context);
1186                }
1187            }
1188            else {
1189                if (resolutionResults.isAmbiguity()) {
1190                    context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls()));
1191                }
1192                else {
1193                    context.trace.report(EQUALS_MISSING.on(operationSign));
1194                }
1195            }
1196            return rightTypeInfo.replaceType(components.builtIns.getBooleanType());
1197        }
1198    
1199        @NotNull
1200        private KotlinTypeInfo visitComparison(
1201                @NotNull KtBinaryExpression expression,
1202                @NotNull ExpressionTypingContext context,
1203                @NotNull KtSimpleNameExpression operationSign
1204        ) {
1205            KotlinTypeInfo typeInfo = getTypeInfoForBinaryCall(OperatorNameConventions.COMPARE_TO, context, expression);
1206            KotlinType compareToReturnType = typeInfo.getType();
1207            KotlinType type = null;
1208            if (compareToReturnType != null && !compareToReturnType.isError()) {
1209                if (KotlinTypeChecker.DEFAULT.equalTypes(components.builtIns.getIntType(), compareToReturnType)) {
1210                    type = components.builtIns.getBooleanType();
1211                }
1212                else {
1213                    context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType));
1214                }
1215            }
1216            return typeInfo.replaceType(type);
1217        }
1218    
1219        @NotNull
1220        private KotlinTypeInfo visitBooleanOperationExpression(
1221                @Nullable IElementType operationType,
1222                @Nullable KtExpression left,
1223                @Nullable KtExpression right,
1224                @NotNull ExpressionTypingContext context
1225        ) {
1226            KotlinType booleanType = components.builtIns.getBooleanType();
1227            KotlinTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context.replaceExpectedType(booleanType), facade);
1228            DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
1229    
1230            LexicalWritableScope leftScope = newWritableScopeImpl(context, LexicalScopeKind.LEFT_BOOLEAN_EXPRESSION);
1231            // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
1232            boolean isAnd = operationType == KtTokens.ANDAND;
1233            DataFlowInfo flowInfoLeft = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
1234            LexicalWritableScope rightScope = isAnd ? leftScope : newWritableScopeImpl(context, LexicalScopeKind.RIGHT_BOOLEAN_EXPRESSION);
1235    
1236            ExpressionTypingContext contextForRightExpr =
1237                    context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope).replaceExpectedType(booleanType);
1238            if (right != null) {
1239                facade.getTypeInfo(right, contextForRightExpr);
1240            }
1241            return leftTypeInfo.replaceType(booleanType);
1242        }
1243    
1244        @NotNull
1245        private KotlinTypeInfo visitElvisExpression(
1246                @NotNull KtBinaryExpression expression,
1247                @NotNull ExpressionTypingContext contextWithExpectedType
1248        ) {
1249            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
1250            KtExpression left = expression.getLeft();
1251            KtExpression right = expression.getRight();
1252    
1253            if (left == null || right == null) {
1254                getTypeInfoOrNullType(left, context, facade);
1255                return TypeInfoFactoryKt.noTypeInfo(context);
1256            }
1257    
1258            Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Lists.newArrayList(left, right));
1259            ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
1260                    call, ResolveConstruct.ELVIS, Lists.newArrayList("left", "right"),
1261                    Lists.newArrayList(true, false), contextWithExpectedType, null);
1262            KotlinTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
1263            if (ArgumentTypeResolver.isFunctionLiteralArgument(left, context)) {
1264                context.trace.report(USELESS_ELVIS_ON_FUNCTION_LITERAL.on(expression.getOperationReference()));
1265                if (leftTypeInfo == null) return TypeInfoFactoryKt.noTypeInfo(context);
1266            }
1267            assert leftTypeInfo != null : "Left expression was not processed: " + expression;
1268            KotlinType leftType = leftTypeInfo.getType();
1269            if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
1270                context.trace.report(USELESS_ELVIS.on(expression, leftType));
1271            }
1272            KotlinTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext());
1273            if (rightTypeInfo == null && ArgumentTypeResolver.isFunctionLiteralArgument(right, context)) {
1274                // the type is computed later in call completer according to the '?:' semantics as a function
1275                return TypeInfoFactoryKt.noTypeInfo(context);
1276            }
1277            assert rightTypeInfo != null : "Right expression was not processed: " + expression;
1278            boolean loopBreakContinuePossible = leftTypeInfo.getJumpOutPossible() || rightTypeInfo.getJumpOutPossible();
1279            KotlinType rightType = rightTypeInfo.getType();
1280    
1281            // Only left argument DFA is taken into account here: we cannot be sure that right argument is executed
1282            DataFlowInfo dataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getInfo(call.getValueArguments().get(1));
1283            if (leftType != null) {
1284                DataFlowValue leftValue = createDataFlowValue(left, leftType, context);
1285                DataFlowInfo rightDataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
1286                // left argument is considered not-null if it's not-null also in right part or if we have jump in right part
1287                if ((rightType != null && KotlinBuiltIns.isNothingOrNullableNothing(rightType) && !rightType.isMarkedNullable())
1288                    || !rightDataFlowInfo.getPredictableNullability(leftValue).canBeNull()) {
1289                    dataFlowInfo = dataFlowInfo.disequate(leftValue, DataFlowValue.nullValue(components.builtIns));
1290                }
1291            }
1292            KotlinType type = resolvedCall.getResultingDescriptor().getReturnType();
1293            if (type == null || rightType == null) return TypeInfoFactoryKt.noTypeInfo(dataFlowInfo);
1294    
1295            // Sometimes return type for special call for elvis operator might be nullable,
1296            // but result is not nullable if the right type is not nullable
1297            if (!TypeUtils.isNullableType(rightType) && TypeUtils.isNullableType(type)) {
1298                type = TypeUtils.makeNotNullable(type);
1299            }
1300            if (context.contextDependency == DEPENDENT) {
1301                return TypeInfoFactoryKt.createTypeInfo(type, dataFlowInfo);
1302            }
1303    
1304            // If break or continue was possible, take condition check info as the jump info
1305            return TypeInfoFactoryKt.createTypeInfo(components.dataFlowAnalyzer.checkType(type, expression, contextWithExpectedType),
1306                                                    dataFlowInfo,
1307                                                    loopBreakContinuePossible,
1308                                                    context.dataFlowInfo);
1309        }
1310    
1311        @NotNull
1312        public KotlinTypeInfo checkInExpression(
1313                @NotNull KtElement callElement,
1314                @NotNull KtSimpleNameExpression operationSign,
1315                @NotNull ValueArgument leftArgument,
1316                @Nullable KtExpression right,
1317                @NotNull ExpressionTypingContext context
1318        ) {
1319            KtExpression left = leftArgument.getArgumentExpression();
1320            ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
1321            if (right == null) {
1322                if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
1323                return TypeInfoFactoryKt.noTypeInfo(context);
1324            }
1325    
1326            KotlinTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithNoExpectedType);
1327            DataFlowInfo dataFlowInfo = rightTypeInfo.getDataFlowInfo();
1328    
1329            ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, contextWithNoExpectedType);
1330            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1331    
1332            OverloadResolutionResults<FunctionDescriptor> resolutionResult = components.callResolver.resolveCallWithGivenName(
1333                    contextWithDataFlow,
1334                    CallMaker.makeCall(callElement, receiver, null, operationSign, Collections.singletonList(leftArgument)),
1335                    operationSign,
1336                    OperatorNameConventions.CONTAINS);
1337            KotlinType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
1338            ensureBooleanResult(operationSign, OperatorNameConventions.CONTAINS, containsType, context);
1339    
1340            if (left != null) {
1341                dataFlowInfo = facade.getTypeInfo(left, contextWithDataFlow).getDataFlowInfo().and(dataFlowInfo);
1342                rightTypeInfo = rightTypeInfo.replaceDataFlowInfo(dataFlowInfo);
1343            }
1344    
1345            if (resolutionResult.isSuccess()) {
1346                return rightTypeInfo.replaceType(components.builtIns.getBooleanType());
1347            }
1348            else {
1349                return rightTypeInfo.clearType();
1350            }
1351        }
1352    
1353    
1354        private boolean ensureBooleanResult(KtExpression operationSign, Name name, KotlinType resultType, ExpressionTypingContext context) {
1355            return ensureBooleanResultWithCustomSubject(operationSign, resultType, "'" + name + "'", context);
1356        }
1357    
1358        private boolean ensureBooleanResultWithCustomSubject(
1359                KtExpression operationSign,
1360                KotlinType resultType,
1361                String subjectName,
1362                ExpressionTypingContext context
1363        ) {
1364            if (resultType != null) {
1365                // TODO : Relax?
1366                if (!components.builtIns.isBooleanOrSubtype(resultType)) {
1367                    context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, subjectName, components.builtIns.getBooleanType(), resultType));
1368                    return false;
1369                }
1370            }
1371            return true;
1372        }
1373    
1374        private void ensureNonemptyIntersectionOfOperandTypes(KtBinaryExpression expression, final ExpressionTypingContext context) {
1375            KtExpression left = expression.getLeft();
1376            if (left == null) return;
1377    
1378            KtExpression right = expression.getRight();
1379    
1380            // TODO : duplicated effort for == and !=
1381            KotlinType leftType = facade.getTypeInfo(left, context).getType();
1382            if (leftType != null && right != null) {
1383                KotlinType rightType = facade.getTypeInfo(right, context).getType();
1384    
1385                if (rightType != null) {
1386                    if (TypeIntersector.isIntersectionEmpty(leftType, rightType)) {
1387                        context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType));
1388                    }
1389                    SenselessComparisonChecker.checkSenselessComparisonWithNull(
1390                            expression, left, right, context,
1391                            new Function1<KtExpression, KotlinType>() {
1392                                @Override
1393                                public KotlinType invoke(KtExpression expression) {
1394                                    return facade.getTypeInfo(expression, context).getType();
1395                                }
1396                            },
1397                            new Function1<DataFlowValue, Nullability>() {
1398                                @Override
1399                                public Nullability invoke(DataFlowValue value) {
1400                                    return context.dataFlowInfo.getPredictableNullability(value);
1401                                }
1402                            });
1403                }
1404            }
1405        }
1406    
1407        @NotNull
1408        private KotlinTypeInfo visitAssignmentOperation(KtBinaryExpression expression, ExpressionTypingContext context) {
1409            return assignmentIsNotAnExpressionError(expression, context);
1410        }
1411    
1412        @NotNull
1413        private KotlinTypeInfo visitAssignment(KtBinaryExpression expression, ExpressionTypingContext context) {
1414            return assignmentIsNotAnExpressionError(expression, context);
1415        }
1416    
1417        @NotNull
1418        private KotlinTypeInfo assignmentIsNotAnExpressionError(KtBinaryExpression expression, ExpressionTypingContext context) {
1419            facade.checkStatementType(expression, context);
1420            context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
1421            return TypeInfoFactoryKt.noTypeInfo(context);
1422        }
1423    
1424        @Override
1425        public KotlinTypeInfo visitArrayAccessExpression(@NotNull KtArrayAccessExpression expression, ExpressionTypingContext context) {
1426            return components.dataFlowAnalyzer.checkType(resolveArrayAccessGetMethod(expression, context), expression, context);
1427        }
1428    
1429        @NotNull
1430        public KotlinTypeInfo getTypeInfoForBinaryCall(
1431                @NotNull Name name,
1432                @NotNull ExpressionTypingContext context,
1433                @NotNull KtBinaryExpression binaryExpression
1434        ) {
1435            KtExpression left = binaryExpression.getLeft();
1436            KotlinTypeInfo typeInfo;
1437            if (left != null) {
1438                //left here is a receiver, so it doesn't depend on expected type
1439                typeInfo = facade.getTypeInfo(left, context.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE));
1440            }
1441            else {
1442                typeInfo = TypeInfoFactoryKt.noTypeInfo(context);
1443            }
1444            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(typeInfo.getDataFlowInfo());
1445    
1446            OverloadResolutionResults<FunctionDescriptor> resolutionResults;
1447            if (left != null) {
1448                ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
1449                resolutionResults = components.callResolver.resolveBinaryCall(
1450                        contextWithDataFlow.replaceScope(context.scope),
1451                        receiver, binaryExpression, name
1452                );
1453            }
1454            else {
1455                resolutionResults = OverloadResolutionResultsImpl.nameNotFound();
1456            }
1457    
1458            if (resolutionResults.isSingleResult()) {
1459                typeInfo = typeInfo.replaceDataFlowInfo(resolutionResults.getResultingCall().getDataFlowInfoForArguments().getResultInfo());
1460            }
1461    
1462            return typeInfo.replaceType(OverloadResolutionResultsUtil.getResultingType(resolutionResults, context.contextDependency));
1463        }
1464    
1465        @Override
1466        public KotlinTypeInfo visitDeclaration(@NotNull KtDeclaration dcl, ExpressionTypingContext context) {
1467            context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl));
1468            return TypeInfoFactoryKt.noTypeInfo(context);
1469        }
1470    
1471        @Override
1472        public KotlinTypeInfo visitRootPackageExpression(@NotNull KtRootPackageExpression expression, ExpressionTypingContext context) {
1473            if (!KtPsiUtil.isLHSOfDot(expression)) {
1474                context.trace.report(PACKAGE_IS_NOT_AN_EXPRESSION.on(expression));
1475            }
1476            return TypeInfoFactoryKt.noTypeInfo(context);
1477        }
1478    
1479        @Override
1480        public KotlinTypeInfo visitStringTemplateExpression(
1481                @NotNull KtStringTemplateExpression expression,
1482                ExpressionTypingContext contextWithExpectedType
1483        ) {
1484            final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE)
1485                                                                           .replaceContextDependency(INDEPENDENT);
1486    
1487            checkLiteralPrefixAndSuffix(expression, context);
1488    
1489            class StringTemplateVisitor extends KtVisitorVoid {
1490                private KotlinTypeInfo typeInfo = TypeInfoFactoryKt.noTypeInfo(context);
1491    
1492                @Override
1493                public void visitStringTemplateEntryWithExpression(@NotNull KtStringTemplateEntryWithExpression entry) {
1494                    KtExpression entryExpression = entry.getExpression();
1495                    if (entryExpression != null) {
1496                        typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
1497                    }
1498                }
1499    
1500                @Override
1501                public void visitEscapeStringTemplateEntry(@NotNull KtEscapeStringTemplateEntry entry) {
1502                    CompileTimeConstantChecker.CharacterWithDiagnostic value =
1503                            CompileTimeConstantChecker.escapedStringToCharacter(entry.getText(), entry);
1504                    Diagnostic diagnostic = value.getDiagnostic();
1505                    if (diagnostic != null) {
1506                        context.trace.report(diagnostic);
1507                    }
1508                }
1509            }
1510            StringTemplateVisitor visitor = new StringTemplateVisitor();
1511            for (KtStringTemplateEntry entry : expression.getEntries()) {
1512                entry.accept(visitor);
1513            }
1514            components.constantExpressionEvaluator.evaluateExpression(expression, context.trace, contextWithExpectedType.expectedType);
1515            return components.dataFlowAnalyzer.checkType(visitor.typeInfo.replaceType(components.builtIns.getStringType()),
1516                                                         expression,
1517                                                         contextWithExpectedType);
1518        }
1519    
1520        private static void checkLiteralPrefixAndSuffix(@NotNull PsiElement expression, ExpressionTypingContext context) {
1521            checkLiteralPrefixOrSuffix(PsiTreeUtil.prevLeaf(expression), context);
1522            checkLiteralPrefixOrSuffix(PsiTreeUtil.nextLeaf(expression), context);
1523        }
1524    
1525        private static void checkLiteralPrefixOrSuffix(PsiElement prefixOrSuffix, ExpressionTypingContext context) {
1526            if (illegalLiteralPrefixOrSuffix(prefixOrSuffix)) {
1527                context.trace.report(Errors.UNSUPPORTED.on(prefixOrSuffix, "literal prefixes and suffixes"));
1528            }
1529        }
1530    
1531        private static boolean illegalLiteralPrefixOrSuffix(@Nullable PsiElement element) {
1532            if (element == null) return false;
1533    
1534            IElementType elementType = element.getNode().getElementType();
1535            return elementType == IDENTIFIER ||
1536                   elementType == INTEGER_LITERAL ||
1537                   elementType == FLOAT_LITERAL ||
1538                   elementType instanceof KtKeywordToken;
1539        }
1540    
1541        @Override
1542        public KotlinTypeInfo visitAnnotatedExpression(@NotNull KtAnnotatedExpression expression, ExpressionTypingContext context) {
1543            return visitAnnotatedExpression(expression, context, false);
1544        }
1545    
1546        public KotlinTypeInfo visitAnnotatedExpression(KtAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
1547            components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace);
1548    
1549            KtExpression baseExpression = expression.getBaseExpression();
1550            if (baseExpression == null) {
1551                return TypeInfoFactoryKt.noTypeInfo(context);
1552            }
1553            return facade.getTypeInfo(baseExpression, context, isStatement);
1554        }
1555    
1556        @Override
1557        public KotlinTypeInfo visitKtElement(@NotNull KtElement element, ExpressionTypingContext context) {
1558            context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
1559            return TypeInfoFactoryKt.noTypeInfo(context);
1560        }
1561    
1562        @NotNull
1563        /*package*/ KotlinTypeInfo resolveArrayAccessSetMethod(
1564                @NotNull KtArrayAccessExpression arrayAccessExpression,
1565                @NotNull KtExpression rightHandSide,
1566                @NotNull ExpressionTypingContext context,
1567                @NotNull BindingTrace traceForResolveResult
1568        ) {
1569            return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
1570        }
1571    
1572        @NotNull
1573        /*package*/ KotlinTypeInfo resolveArrayAccessGetMethod(
1574                @NotNull KtArrayAccessExpression arrayAccessExpression,
1575                @NotNull ExpressionTypingContext context
1576        ) {
1577            return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
1578        }
1579    
1580        @NotNull
1581        private KotlinTypeInfo resolveArrayAccessSpecialMethod(
1582                @NotNull KtArrayAccessExpression arrayAccessExpression,
1583                @Nullable KtExpression rightHandSide, //only for 'set' method
1584                @NotNull ExpressionTypingContext oldContext,
1585                @NotNull BindingTrace traceForResolveResult,
1586                boolean isGet
1587        ) {
1588            KtExpression arrayExpression = arrayAccessExpression.getArrayExpression();
1589            if (arrayExpression == null) return TypeInfoFactoryKt.noTypeInfo(oldContext);
1590    
1591    
1592            KotlinTypeInfo arrayTypeInfo = facade.safeGetTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
1593                    .replaceContextDependency(INDEPENDENT));
1594            KotlinType arrayType = ExpressionTypingUtils.safeGetType(arrayTypeInfo);
1595    
1596            ExpressionTypingContext context = oldContext.replaceDataFlowInfo(arrayTypeInfo.getDataFlowInfo());
1597            ExpressionReceiver receiver = ExpressionReceiver.Companion.create(arrayExpression, arrayType, context.trace.getBindingContext());
1598            if (!isGet) assert rightHandSide != null;
1599    
1600            Call call = isGet
1601                        ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD)
1602                        : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD);
1603            OverloadResolutionResults<FunctionDescriptor> functionResults = components.callResolver.resolveCallWithGivenName(
1604                    context, call, arrayAccessExpression, Name.identifier(isGet ? "get" : "set"));
1605    
1606            List<KtExpression> indices = arrayAccessExpression.getIndexExpressions();
1607            // The accumulated data flow info of all index expressions is saved on the last index
1608            KotlinTypeInfo resultTypeInfo = arrayTypeInfo;
1609            if (!indices.isEmpty()) {
1610                resultTypeInfo = facade.getTypeInfo(indices.get(indices.size() - 1), context);
1611            }
1612    
1613            if (!isGet) {
1614                resultTypeInfo = facade.getTypeInfo(rightHandSide, context);
1615            }
1616    
1617            if (!functionResults.isSingleResult()) {
1618                traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression));
1619                return resultTypeInfo.clearType();
1620            }
1621            traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression,
1622                                         functionResults.getResultingCall());
1623            return resultTypeInfo.replaceType(functionResults.getResultingDescriptor().getReturnType());
1624        }
1625    }