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