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