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