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