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