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