001    /*
002     * Copyright 2010-2013 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.jet.lang.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 org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.jet.lang.descriptors.*;
026    import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
027    import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
028    import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor;
029    import org.jetbrains.jet.lang.diagnostics.Diagnostic;
030    import org.jetbrains.jet.lang.diagnostics.Errors;
031    import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
032    import org.jetbrains.jet.lang.psi.*;
033    import org.jetbrains.jet.lang.resolve.*;
034    import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver;
035    import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver;
036    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
037    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
038    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
039    import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability;
040    import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
041    import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
042    import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
043    import org.jetbrains.jet.lang.resolve.calls.model.DataFlowInfoForArgumentsImpl;
044    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
045    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
046    import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
047    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
048    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
049    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
050    import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
051    import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
052    import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
053    import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
054    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
055    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantChecker;
056    import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant;
057    import org.jetbrains.jet.lang.resolve.name.Name;
058    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
059    import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
060    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
061    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
062    import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
063    import org.jetbrains.jet.lang.types.*;
064    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
065    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
066    import org.jetbrains.jet.lexer.JetTokens;
067    import org.jetbrains.jet.util.slicedmap.WritableSlice;
068    import org.jetbrains.jet.utils.ThrowingList;
069    
070    import java.util.Collection;
071    import java.util.Collections;
072    import java.util.List;
073    
074    import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
075    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
076    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
077    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
078    import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
079    import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
080    import static org.jetbrains.jet.lang.resolve.source.SourcePackage.toSourceElement;
081    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
082    import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
083    import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
084    import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
085    import static org.jetbrains.jet.lang.types.expressions.TypeReconstructionUtil.reconstructBareType;
086    import static org.jetbrains.jet.lexer.JetTokens.AS_KEYWORD;
087    import static org.jetbrains.jet.lexer.JetTokens.AS_SAFE;
088    
089    @SuppressWarnings("SuspiciousMethodCalls")
090    public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
091    
092        private static final TokenSet BARE_TYPES_ALLOWED = TokenSet.create(AS_KEYWORD, AS_SAFE);
093    
094        protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade) {
095            super(facade);
096        }
097    
098        @Override
099        public JetTypeInfo visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, ExpressionTypingContext context) {
100            // TODO : other members
101            // TODO : type substitutions???
102            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
103            JetTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context);
104            JetType type = DataFlowUtils.checkType(typeInfo.getType(), expression, context);
105            ExpressionTypingUtils.checkCapturingInClosure(expression, context.trace, context.scope);
106            return JetTypeInfo.create(type, typeInfo.getDataFlowInfo()); // TODO : Extensions to this
107        }
108    
109        @Override
110        public JetTypeInfo visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, ExpressionTypingContext context) {
111            return visitParenthesizedExpression(expression, context, false);
112        }
113    
114        public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) {
115            JetExpression innerExpression = expression.getExpression();
116            if (innerExpression == null) {
117                return JetTypeInfo.create(null, context.dataFlowInfo);
118            }
119            return facade.getTypeInfo(innerExpression, context.replaceScope(context.scope), isStatement);
120        }
121    
122        @Override
123        public JetTypeInfo visitConstantExpression(@NotNull JetConstantExpression expression, ExpressionTypingContext context) {
124            CompileTimeConstant<?> value = ConstantExpressionEvaluator.OBJECT$.evaluate(expression, context.trace, context.expectedType);
125    
126            if (!(value instanceof IntegerValueTypeConstant)) {
127                CompileTimeConstantChecker compileTimeConstantChecker = context.getCompileTimeConstantChecker();
128                boolean hasError = compileTimeConstantChecker.checkConstantExpressionType(value, expression, context.expectedType);
129                if (hasError) {
130                    IElementType elementType = expression.getNode().getElementType();
131                    return JetTypeInfo.create(getDefaultType(elementType), context.dataFlowInfo);
132                }
133            }
134    
135            assert value != null : "CompileTimeConstant should be evaluated for constant expression or an error should be recorded " + expression.getText();
136            return createCompileTimeConstantTypeInfo(value, expression, context);
137        }
138    
139        @Override
140        public JetTypeInfo visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) {
141            ExpressionTypingContext contextWithNoExpectedType =
142                    context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
143            JetExpression left = expression.getLeft();
144            JetTypeReference right = expression.getRight();
145            if (right == null) {
146                JetTypeInfo leftTypeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
147                return JetTypeInfo.create(null, leftTypeInfo.getDataFlowInfo());
148            }
149    
150            IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
151    
152            boolean allowBareTypes = BARE_TYPES_ALLOWED.contains(operationType);
153            TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, allowBareTypes);
154            PossiblyBareType possiblyBareTarget = components.expressionTypingServices.getTypeResolver().resolvePossiblyBareType(typeResolutionContext, right);
155    
156            if (operationType == JetTokens.COLON) {
157                // We do not allow bare types on static assertions, because static assertions provide an expected type for their argument,
158                // thus causing a circularity in type dependencies
159                assert !possiblyBareTarget.isBare() : "Bare types should not be allowed for static assertions, because argument inference makes no sense there";
160                JetType targetType = possiblyBareTarget.getActualType();
161    
162                JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
163                checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
164                return DataFlowUtils.checkType(targetType, expression, context, typeInfo.getDataFlowInfo());
165            }
166    
167            JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
168    
169            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
170            JetType subjectType = typeInfo.getType();
171            JetType targetType = reconstructBareType(right, possiblyBareTarget, subjectType, context.trace);
172    
173            if (subjectType != null) {
174                checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, subjectType);
175                dataFlowInfo = typeInfo.getDataFlowInfo();
176                if (operationType == AS_KEYWORD) {
177                    DataFlowValue value = DataFlowValueFactory.createDataFlowValue(left, subjectType, context.trace.getBindingContext());
178                    dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType);
179                }
180            }
181    
182            JetType result = operationType == AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
183            return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
184        }
185    
186        private void checkBinaryWithTypeRHS(
187                @NotNull JetBinaryExpressionWithTypeRHS expression,
188                @NotNull ExpressionTypingContext context,
189                @NotNull JetType targetType,
190                @Nullable JetType actualType
191        ) {
192            if (actualType == null) return;
193            JetSimpleNameExpression operationSign = expression.getOperationReference();
194            IElementType operationType = operationSign.getReferencedNameElementType();
195            if (operationType == JetTokens.COLON) {
196                return;
197            }
198            if (operationType != JetTokens.AS_KEYWORD && operationType != JetTokens.AS_SAFE) {
199                context.trace.report(UNSUPPORTED.on(operationSign, "binary operation with type RHS"));
200                return;
201            }
202            checkForCastImpossibility(expression, actualType, targetType, context);
203        }
204    
205        private void checkForCastImpossibility(
206                JetBinaryExpressionWithTypeRHS expression,
207                JetType actualType,
208                JetType targetType,
209                ExpressionTypingContext context
210        ) {
211            if (actualType == null || noExpectedType(targetType)) return;
212    
213            if (!CastDiagnosticsUtil.isCastPossible(actualType, targetType, components.platformToKotlinClassMap)) {
214                context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference()));
215            }
216            else {
217                JetTypeChecker typeChecker = JetTypeChecker.DEFAULT;
218                // Upcast?
219                if (typeChecker.isSubtypeOf(actualType, targetType)) {
220                    if (!typeChecker.isSubtypeOf(targetType, actualType)) {
221                        // proper upcast: String as Any
222                        context.trace.report(USELESS_CAST_STATIC_ASSERT_IS_FINE.on(expression.getOperationReference()));
223                    }
224                    else {
225                        // cast to itself: String as String
226                        context.trace.report(USELESS_CAST.on(expression.getOperationReference()));
227                    }
228                }
229                else if (CastDiagnosticsUtil.isCastErased(actualType, targetType, typeChecker)) {
230                    context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType));
231                }
232            }
233        }
234    
235        @Override
236        public JetTypeInfo visitThisExpression(@NotNull JetThisExpression expression, ExpressionTypingContext context) {
237            JetType result = null;
238            LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, false);
239    
240            switch (resolutionResult.getCode()) {
241                case LABEL_RESOLUTION_ERROR:
242                    // Do nothing, the error is already reported
243                    break;
244                case NO_THIS:
245                    context.trace.report(NO_THIS.on(expression));
246                    break;
247                case SUCCESS:
248                    result = resolutionResult.getReceiverParameterDescriptor().getType();
249                    context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
250                    break;
251            }
252            return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
253        }
254    
255        @Override
256        public JetTypeInfo visitSuperExpression(@NotNull JetSuperExpression expression, ExpressionTypingContext context) {
257            LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, true);
258    
259            if (!JetPsiUtil.isLHSOfDot(expression)) {
260                context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText()));
261                return errorInSuper(expression, context);
262            }
263    
264            switch (resolutionResult.getCode()) {
265                case LABEL_RESOLUTION_ERROR:
266                    // The error is already reported
267                    return errorInSuper(expression, context);
268                case NO_THIS:
269                    context.trace.report(SUPER_NOT_AVAILABLE.on(expression));
270                    return errorInSuper(expression, context);
271                case SUCCESS:
272                    JetType result = checkPossiblyQualifiedSuper(expression, context, resolutionResult.getReceiverParameterDescriptor());
273                    if (result != null) {
274                        context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
275                    }
276                    return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
277            }
278            throw new IllegalStateException("Unknown code: " + resolutionResult.getCode());
279        }
280    
281        private JetTypeInfo errorInSuper(JetSuperExpression expression, ExpressionTypingContext context) {
282            JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
283            if (superTypeQualifier != null) {
284                components.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true);
285            }
286            return JetTypeInfo.create(null, context.dataFlowInfo);
287        }
288    
289        private JetType checkPossiblyQualifiedSuper(
290                JetSuperExpression expression,
291                ExpressionTypingContext context,
292                ReceiverParameterDescriptor thisReceiver
293        ) {
294            JetType result = null;
295            JetType thisType = thisReceiver.getType();
296            Collection<JetType> supertypes = thisType.getConstructor().getSupertypes();
297            TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
298    
299            JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
300            if (superTypeQualifier != null) {
301                JetTypeElement typeElement = superTypeQualifier.getTypeElement();
302    
303                DeclarationDescriptor classifierCandidate = null;
304                JetType supertype = null;
305                PsiElement redundantTypeArguments = null;
306                if (typeElement instanceof JetUserType) {
307                    JetUserType userType = (JetUserType) typeElement;
308                    // This may be just a superclass name even if the superclass is generic
309                    if (userType.getTypeArguments().isEmpty()) {
310                        classifierCandidate = components.expressionTypingServices.getTypeResolver().resolveClass(context.scope, userType, context.trace);
311                    }
312                    else {
313                        supertype = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true);
314                        redundantTypeArguments = userType.getTypeArgumentList();
315                    }
316                }
317                else {
318                    supertype = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true);
319                }
320    
321                if (supertype != null) {
322                    if (supertypes.contains(supertype)) {
323                        result = supertype;
324                    }
325                }
326                else if (classifierCandidate instanceof ClassDescriptor) {
327                    ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
328    
329                    for (JetType declaredSupertype : supertypes) {
330                        if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
331                            result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
332                            break;
333                        }
334                    }
335                }
336    
337                boolean validClassifier = classifierCandidate != null && !ErrorUtils.isError(classifierCandidate);
338                boolean validType = supertype != null && !supertype.isError();
339                if (result == null && (validClassifier || validType)) {
340                    context.trace.report(NOT_A_SUPERTYPE.on(superTypeQualifier));
341                }
342                else if (redundantTypeArguments != null) {
343                    context.trace.report(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER.on(redundantTypeArguments));
344                }
345            }
346            else {
347                if (supertypes.size() > 1) {
348                    context.trace.report(AMBIGUOUS_SUPER.on(expression));
349                }
350                else {
351                    // supertypes may be empty when all the supertypes are error types (are not resolved, for example)
352                    JetType type = supertypes.isEmpty()
353                                   ? KotlinBuiltIns.getInstance().getAnyType()
354                                   : supertypes.iterator().next();
355                    result = substitutor.substitute(type, Variance.INVARIANT);
356                }
357            }
358            if (result != null) {
359                if (DescriptorUtils.isTrait(thisType.getConstructor().getDeclarationDescriptor())) {
360                    if (DescriptorUtils.isClass(result.getConstructor().getDeclarationDescriptor())) {
361                        context.trace.report(SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT.on(expression));
362                    }
363                }
364                context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
365                context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
366            }
367            if (superTypeQualifier != null) {
368                context.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, superTypeQualifier, context.scope);
369            }
370            return result;
371        }
372    
373        @NotNull // No class receivers
374        private static LabelResolver.LabeledReceiverResolutionResult resolveToReceiver(
375                JetInstanceExpressionWithLabel expression,
376                ExpressionTypingContext context,
377                boolean onlyClassReceivers
378        ) {
379            String labelName = expression.getLabelName();
380            if (labelName != null) {
381                LabelResolver.LabeledReceiverResolutionResult resolutionResult =
382                        LabelResolver.INSTANCE.resolveThisOrSuperLabel(expression, context, Name.identifier(labelName));
383                if (resolutionResult.success()) {
384                    ReceiverParameterDescriptor receiverParameterDescriptor = resolutionResult.getReceiverParameterDescriptor();
385                    recordThisOrSuperCallInTraceAndCallExtension(context, receiverParameterDescriptor, expression);
386                    if (onlyClassReceivers && !isDeclaredInClass(receiverParameterDescriptor)) {
387                        return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(NO_RECEIVER_PARAMETER);
388                    }
389                }
390                return resolutionResult;
391            }
392            else {
393                ReceiverParameterDescriptor result = NO_RECEIVER_PARAMETER;
394                List<ReceiverParameterDescriptor> receivers = context.scope.getImplicitReceiversHierarchy();
395                if (onlyClassReceivers) {
396                    for (ReceiverParameterDescriptor receiver : receivers) {
397                        if (isDeclaredInClass(receiver)) {
398                            result = receiver;
399                            break;
400                        }
401                    }
402                }
403                else if (!receivers.isEmpty()) {
404                    result = receivers.get(0);
405                }
406                if (result != NO_RECEIVER_PARAMETER) {
407                    context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration());
408                    recordThisOrSuperCallInTraceAndCallExtension(context, result, expression);
409                }
410                return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result);
411            }
412        }
413    
414        private static void recordThisOrSuperCallInTraceAndCallExtension(
415                ExpressionTypingContext context,
416                ReceiverParameterDescriptor descriptor,
417                JetExpression expression
418        ) {
419            BindingTrace trace = context.trace;
420            Call call = CallMaker.makeCall(expression, NO_RECEIVER, null, expression, Collections.<ValueArgument>emptyList());
421            ResolutionCandidate<ReceiverParameterDescriptor> resolutionCandidate =
422                    ResolutionCandidate.create(
423                            call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false);
424    
425            ResolvedCallImpl<ReceiverParameterDescriptor> resolvedCall =
426                    ResolvedCallImpl.create(resolutionCandidate,
427                                            TemporaryBindingTrace.create(trace, "Fake trace for fake 'this' or 'super' resolved call"),
428                                            TracingStrategy.EMPTY,
429                                            new DataFlowInfoForArgumentsImpl(call));
430            resolvedCall.markCallAsCompleted();
431    
432            trace.record(RESOLVED_CALL, call, resolvedCall);
433            trace.record(CALL, expression, call);
434    
435            context.callResolverExtension.run(resolvedCall,
436                                              BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.DISABLED));
437        }
438    
439        private static boolean isDeclaredInClass(ReceiverParameterDescriptor receiver) {
440            return receiver.getContainingDeclaration() instanceof ClassDescriptor;
441        }
442    
443        @Override
444        public JetTypeInfo visitBlockExpression(@NotNull JetBlockExpression expression, ExpressionTypingContext context) {
445            return components.expressionTypingServices.getBlockReturnedType(expression, context, false);
446        }
447    
448        @Override
449        public JetTypeInfo visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, ExpressionTypingContext context) {
450            JetTypeReference typeReference = expression.getTypeReference();
451    
452            JetType receiverType =
453                    typeReference == null
454                    ? null
455                    : components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, false);
456    
457            JetSimpleNameExpression callableReference = expression.getCallableReference();
458            if (callableReference.getReferencedName().isEmpty()) {
459                context.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference));
460                JetType errorType = ErrorUtils.createErrorType("Empty callable reference");
461                return DataFlowUtils.checkType(errorType, expression, context, context.dataFlowInfo);
462            }
463    
464            JetType result = getCallableReferenceType(expression, receiverType, context);
465            return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
466        }
467    
468        @Nullable
469        private JetType getCallableReferenceType(
470                @NotNull JetCallableReferenceExpression expression,
471                @Nullable JetType lhsType,
472                @NotNull ExpressionTypingContext context
473        ) {
474            JetSimpleNameExpression reference = expression.getCallableReference();
475    
476            boolean[] result = new boolean[1];
477            CallableDescriptor descriptor = resolveCallableReferenceTarget(lhsType, context, expression, result);
478    
479            if (!result[0]) {
480                context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
481            }
482            if (descriptor == null) return null;
483    
484            ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
485            ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
486            if (receiverParameter != null && expectedThisObject != null && descriptor instanceof CallableMemberDescriptor) {
487                context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, (CallableMemberDescriptor) descriptor));
488                return null;
489            }
490    
491            JetType receiverType = null;
492            if (receiverParameter != null) {
493                receiverType = receiverParameter.getType();
494            }
495            else if (expectedThisObject != null) {
496                receiverType = expectedThisObject.getType();
497            }
498            boolean isExtension = receiverParameter != null;
499    
500            if (descriptor instanceof FunctionDescriptor) {
501                return createFunctionReferenceType(expression, context, (FunctionDescriptor) descriptor, receiverType, isExtension);
502            }
503            else if (descriptor instanceof PropertyDescriptor) {
504                return createPropertyReferenceType(expression, context, (PropertyDescriptor) descriptor, receiverType, isExtension);
505            }
506            else if (descriptor instanceof VariableDescriptor) {
507                context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
508                return null;
509            }
510    
511            throw new UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: " + descriptor);
512        }
513    
514        @Nullable
515        private JetType createFunctionReferenceType(
516                @NotNull JetCallableReferenceExpression expression,
517                @NotNull ExpressionTypingContext context,
518                @NotNull FunctionDescriptor descriptor,
519                @Nullable JetType receiverType,
520                boolean isExtension
521        ) {
522            //noinspection ConstantConditions
523            JetType type = components.reflectionTypes.getKFunctionType(
524                    Annotations.EMPTY,
525                    receiverType,
526                    getValueParametersTypes(descriptor.getValueParameters()),
527                    descriptor.getReturnType(),
528                    isExtension
529            );
530    
531            if (type.isError()) {
532                context.trace.report(REFLECTION_TYPES_NOT_LOADED.on(expression.getDoubleColonTokenReference()));
533                return null;
534            }
535    
536            AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
537                    context.scope.getContainingDeclaration(),
538                    Annotations.EMPTY,
539                    CallableMemberDescriptor.Kind.DECLARATION,
540                    toSourceElement(expression)
541            );
542    
543            FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
544    
545            context.trace.record(FUNCTION, expression, functionDescriptor);
546    
547            return type;
548        }
549    
550        @Nullable
551        private JetType createPropertyReferenceType(
552                @NotNull JetCallableReferenceExpression expression,
553                @NotNull ExpressionTypingContext context,
554                @NotNull PropertyDescriptor descriptor,
555                @Nullable JetType receiverType,
556                boolean isExtension
557        ) {
558            JetType type = components.reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.getType(), isExtension,
559                                                                       descriptor.isVar());
560    
561            if (type.isError()) {
562                context.trace.report(REFLECTION_TYPES_NOT_LOADED.on(expression.getDoubleColonTokenReference()));
563                return null;
564            }
565    
566            LocalVariableDescriptor localVariable =
567                    new LocalVariableDescriptor(context.scope.getContainingDeclaration(), Annotations.EMPTY, Name.special("<anonymous>"),
568                                                type, /* mutable = */ false, toSourceElement(expression));
569    
570            context.trace.record(VARIABLE, expression, localVariable);
571    
572            return type;
573        }
574    
575        @Nullable
576        private CallableDescriptor resolveCallableReferenceTarget(
577                @Nullable JetType lhsType,
578                @NotNull ExpressionTypingContext context,
579                @NotNull JetCallableReferenceExpression expression,
580                @NotNull boolean[] result
581        ) {
582            JetSimpleNameExpression reference = expression.getCallableReference();
583    
584            if (lhsType == null) {
585                return resolveCallableNotCheckingArguments(reference, NO_RECEIVER, context, result);
586            }
587    
588            ClassifierDescriptor classifier = lhsType.getConstructor().getDeclarationDescriptor();
589            if (!(classifier instanceof ClassDescriptor)) {
590                context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(expression));
591                return null;
592            }
593    
594            JetScope staticScope = ((ClassDescriptor) classifier).getStaticScope();
595            TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
596                    context, "trace to resolve callable reference in static scope", reference);
597            CallableDescriptor possibleStatic = resolveCallableNotCheckingArguments(
598                    reference, NO_RECEIVER, context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
599            if (result[0]) {
600                temporaryForStatic.commit();
601                return possibleStatic;
602            }
603    
604            JetScope staticNestedClasses = getStaticNestedClassesScope((ClassDescriptor) classifier);
605            TemporaryTraceAndCache temporaryForNested = TemporaryTraceAndCache.create(
606                    context, "trace to resolve callable reference in static nested classes scope", reference);
607            CallableDescriptor possibleNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
608                    context.replaceTraceAndCache(temporaryForNested).replaceScope(staticNestedClasses), result);
609            if (result[0]) {
610                temporaryForNested.commit();
611                return possibleNestedClassConstructor;
612            }
613    
614            ReceiverValue receiver = new TransientReceiver(lhsType);
615            TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
616                    context, "trace to resolve callable reference with receiver", reference);
617            CallableDescriptor descriptor = resolveCallableNotCheckingArguments(
618                    reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
619            if (result[0]) {
620                temporaryWithReceiver.commit();
621                return descriptor;
622            }
623    
624            return null;
625        }
626    
627        @Nullable
628        private CallableDescriptor resolveCallableNotCheckingArguments(
629                @NotNull JetSimpleNameExpression reference,
630                @NotNull ReceiverValue receiver,
631                @NotNull ExpressionTypingContext context,
632                @NotNull boolean[] result
633        ) {
634            Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
635    
636            TemporaryTraceAndCache funTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as function",
637                                                                            reference);
638            ResolvedCall<FunctionDescriptor> function = components.expressionTypingServices.getCallExpressionResolver()
639                    .getResolvedCallForFunction(call, reference, context.replaceTraceAndCache(funTrace).replaceExpectedType(NO_EXPECTED_TYPE),
640                                                CheckValueArgumentsMode.DISABLED, result);
641            if (result[0]) {
642                funTrace.commit();
643    
644                if (function instanceof VariableAsFunctionResolvedCall) {
645                    context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
646                    return null;
647                }
648    
649                return function != null ? function.getResultingDescriptor() : null;
650            }
651    
652            TemporaryTraceAndCache varTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as variable",
653                                                                            reference);
654            OverloadResolutionResults<VariableDescriptor> variableResults =
655                    components.expressionTypingServices.getCallResolver().resolveSimpleProperty(
656                            BasicCallResolutionContext.create(context.replaceTraceAndCache(varTrace).replaceExpectedType(NO_EXPECTED_TYPE),
657                                                              call, CheckValueArgumentsMode.DISABLED)
658                    );
659            if (!variableResults.isNothing()) {
660                ResolvedCall<VariableDescriptor> variable =
661                        OverloadResolutionResultsUtil.getResultingCall(variableResults, context.contextDependency);
662    
663                varTrace.commit();
664                if (variable != null) {
665                    result[0] = true;
666                    return variable.getResultingDescriptor();
667                }
668            }
669    
670            return null;
671        }
672    
673        @Override
674        public JetTypeInfo visitQualifiedExpression(@NotNull JetQualifiedExpression expression, ExpressionTypingContext context) {
675            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
676            return callExpressionResolver.getQualifiedExpressionTypeInfo(expression, context);
677        }
678    
679        @Override
680        public JetTypeInfo visitCallExpression(@NotNull JetCallExpression expression, ExpressionTypingContext context) {
681            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
682            return callExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context);
683        }
684    
685        @Override
686        public JetTypeInfo visitUnaryExpression(@NotNull JetUnaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
687            ExpressionTypingContext context = isUnaryExpressionDependentOnExpectedType(expression)
688                    ? contextWithExpectedType
689                    : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
690    
691            JetExpression baseExpression = expression.getBaseExpression();
692            if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
693    
694            JetSimpleNameExpression operationSign = expression.getOperationReference();
695    
696            IElementType operationType = operationSign.getReferencedNameElementType();
697    
698            // Special case for expr!!
699            if (operationType == JetTokens.EXCLEXCL) {
700                return visitExclExclExpression(expression, context);
701            }
702    
703            // Type check the base expression
704            JetTypeInfo typeInfo = facade.safeGetTypeInfo(baseExpression, context);
705            JetType type = ExpressionTypingUtils.safeGetType(typeInfo);
706            ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type);
707    
708            Call call = CallMaker.makeCall(receiver, expression);
709            DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
710    
711            // Conventions for unary operations
712            Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
713            if (name == null) {
714                context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
715                return JetTypeInfo.create(null, dataFlowInfo);
716            }
717    
718            // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
719            if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) {
720                JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
721                TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace
722                        .create(context.trace, "trace to resolve array access set method for unary expression", expression);
723                ExpressionTypingContext newContext = context.replaceBindingTrace(temporaryBindingTrace);
724                resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression, stubExpression, newContext, context.trace);
725            }
726    
727            // Resolve the operation reference
728            OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(
729                    context, call, expression.getOperationReference(), name);
730    
731            if (!resolutionResults.isSuccess()) {
732                return JetTypeInfo.create(null, dataFlowInfo);
733            }
734    
735            // Computing the return type
736            JetType returnType = resolutionResults.getResultingDescriptor().getReturnType();
737            JetType result;
738            if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
739                assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
740                if (KotlinBuiltIns.getInstance().isUnit(returnType)) {
741                    result = ErrorUtils.createErrorType(KotlinBuiltIns.getInstance().getUnit().getName().asString());
742                    context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
743                }
744                else {
745                    JetType receiverType = receiver.getType();
746                    if (!JetTypeChecker.DEFAULT.isSubtypeOf(returnType, receiverType)) {
747                        context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
748                    }
749                    else {
750                        context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
751    
752                        checkLValue(context.trace, baseExpression);
753                    }
754                    // TODO : Maybe returnType?
755                    result = receiverType;
756                }
757            }
758            else {
759                result = returnType;
760            }
761    
762            CompileTimeConstant<?> value = ConstantExpressionEvaluator.OBJECT$.evaluate(expression, contextWithExpectedType.trace,
763                                                                                        contextWithExpectedType.expectedType);
764            if (value != null) {
765                return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
766            }
767    
768            return DataFlowUtils.checkType(result, expression, contextWithExpectedType, dataFlowInfo);
769        }
770    
771        @NotNull
772        public static JetTypeInfo createCompileTimeConstantTypeInfo(
773                @NotNull CompileTimeConstant<?> value,
774                @NotNull JetExpression expression,
775                @NotNull ExpressionTypingContext context
776        ) {
777            JetType expressionType = value.getType(KotlinBuiltIns.getInstance());
778            if (value instanceof IntegerValueTypeConstant && context.contextDependency == INDEPENDENT) {
779                expressionType = ((IntegerValueTypeConstant) value).getType(context.expectedType);
780                ArgumentTypeResolver.updateNumberType(expressionType, expression, context.trace);
781            }
782    
783            return DataFlowUtils.checkType(expressionType, expression, context, context.dataFlowInfo);
784        }
785    
786        private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) {
787            JetExpression baseExpression = expression.getBaseExpression();
788            assert baseExpression != null;
789            JetSimpleNameExpression operationSign = expression.getOperationReference();
790            assert operationSign.getReferencedNameElementType() == JetTokens.EXCLEXCL;
791    
792            Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Collections.singletonList(baseExpression));
793            components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
794                    call, "ExclExcl", Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null);
795            JetTypeInfo baseTypeInfo = BindingContextUtils.getRecordedTypeInfo(baseExpression, context.trace.getBindingContext());
796            assert baseTypeInfo != null : "Base expression was not processed: " + expression;
797            JetType baseType = baseTypeInfo.getType();
798            if (baseType == null) {
799                return baseTypeInfo;
800            }
801            DataFlowInfo dataFlowInfo = baseTypeInfo.getDataFlowInfo();
802            if (isKnownToBeNotNull(baseExpression, context) && !baseType.isError()) {
803                context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, baseType));
804            }
805            else {
806                DataFlowValue value = DataFlowValueFactory.createDataFlowValue(baseExpression, baseType, context.trace.getBindingContext());
807                dataFlowInfo = dataFlowInfo.disequate(value, DataFlowValue.NULL);
808            }
809            return JetTypeInfo.create(TypeUtils.makeNotNullable(baseType), dataFlowInfo);
810        }
811    
812        @Override
813        public JetTypeInfo visitLabeledExpression(
814                @NotNull JetLabeledExpression expression, ExpressionTypingContext context
815        ) {
816            return visitLabeledExpression(expression, context, false);
817        }
818    
819        @NotNull
820        public JetTypeInfo visitLabeledExpression(
821                @NotNull JetLabeledExpression expression,
822                @NotNull ExpressionTypingContext context,
823                boolean isStatement
824        ) {
825            JetExpression baseExpression = expression.getBaseExpression();
826            if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
827    
828            return facade.getTypeInfo(baseExpression, context, isStatement);
829        }
830    
831        private static boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) {
832            JetType type = context.trace.get(EXPRESSION_TYPE, expression);
833            assert type != null : "This method is only supposed to be called when the type is not null";
834            return isKnownToBeNotNull(expression, type, context);
835        }
836    
837        private static boolean isKnownToBeNotNull(JetExpression expression, JetType jetType, ExpressionTypingContext context) {
838            DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, jetType, context.trace.getBindingContext());
839            return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull();
840        }
841    
842        public static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) {
843            checkLValue(trace, expression, false);
844        }
845    
846        private static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expressionWithParenthesis, boolean canBeThis) {
847            JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
848            if (expression instanceof JetArrayAccessExpression) {
849                JetExpression arrayExpression = ((JetArrayAccessExpression) expression).getArrayExpression();
850                if (arrayExpression != null) {
851                    checkLValue(trace, arrayExpression, true);
852                }
853                return;
854            }
855            if (canBeThis && expression instanceof JetThisExpression) return;
856            VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
857    
858            JetExpression reportOn = expression != null ? expression : expressionWithParenthesis;
859            if (variable instanceof PropertyDescriptor) {
860                PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
861                if (propertyDescriptor.isSetterProjectedOut()) {
862                    trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
863                }
864            }
865    
866            if (variable == null) {
867                trace.report(VARIABLE_EXPECTED.on(reportOn));
868            }
869        }
870    
871        @Override
872        public JetTypeInfo visitBinaryExpression(@NotNull JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
873            ExpressionTypingContext context = isBinaryExpressionDependentOnExpectedType(expression)
874                    ? contextWithExpectedType
875                    : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
876    
877            JetSimpleNameExpression operationSign = expression.getOperationReference();
878            JetExpression left = expression.getLeft();
879            JetExpression right = expression.getRight();
880            IElementType operationType = operationSign.getReferencedNameElementType();
881    
882            JetTypeInfo result;
883    
884            //Expressions that can depend on expected type
885            if (operationType == JetTokens.IDENTIFIER) {
886                Name referencedName = operationSign.getReferencedNameAsName();
887                result = getTypeInfoForBinaryCall(referencedName, context, expression);
888            }
889            else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) {
890                Name referencedName = OperatorConventions.BINARY_OPERATION_NAMES.get(operationType);
891                result = getTypeInfoForBinaryCall(referencedName, context, expression);
892            }
893            else if (operationType == JetTokens.ELVIS) {
894                //base expression of elvis operator is checked for 'type mismatch', so the whole expression shouldn't be checked
895                return visitElvisExpression(expression, context);
896            }
897    
898            //Expressions that don't depend on expected type
899            else if (operationType == JetTokens.EQ) {
900                result = visitAssignment(expression, context);
901            }
902            else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
903                result = visitAssignmentOperation(expression, context);
904            }
905            else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
906                result = visitComparison(expression, context, operationSign);
907            }
908            else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
909                result = visitEquality(expression, context, operationSign, left, right);
910            }
911            else if (OperatorConventions.IDENTITY_EQUALS_OPERATIONS.contains(operationType)) {
912                context.trace.record(REFERENCE_TARGET, operationSign, KotlinBuiltIns.getInstance().getIdentityEquals());
913                ensureNonemptyIntersectionOfOperandTypes(expression, context);
914                // TODO : Check comparison pointlessness
915                result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), context.dataFlowInfo);
916            }
917            else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
918                ValueArgument leftArgument = CallMaker.makeValueArgument(left, left != null ? left : operationSign);
919                result = checkInExpression(expression, operationSign, leftArgument, right, context);
920            }
921            else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
922                result = visitBooleanOperationExpression(operationType, left, right, context);
923            }
924            else {
925                context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
926                result = JetTypeInfo.create(null, context.dataFlowInfo);
927            }
928            CompileTimeConstant<?> value = ConstantExpressionEvaluator.OBJECT$.
929                    evaluate(expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType);
930            if (value != null) {
931                return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
932            }
933            return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
934        }
935    
936        private JetTypeInfo visitEquality(
937                JetBinaryExpression expression,
938                ExpressionTypingContext context,
939                JetSimpleNameExpression operationSign,
940                final JetExpression left,
941                final JetExpression right
942        ) {
943            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
944            if (right == null || left == null) {
945                ExpressionTypingUtils.getTypeInfoOrNullType(right, context, facade);
946                ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
947                return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo);
948            }
949            ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context);
950    
951            JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
952    
953            dataFlowInfo = leftTypeInfo.getDataFlowInfo();
954            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
955    
956            JetTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithDataFlow);
957            dataFlowInfo = rightTypeInfo.getDataFlowInfo();
958    
959            TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create(
960                    context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
961            traceInterpretingRightAsNullableAny.record(EXPRESSION_TYPE, right, KotlinBuiltIns.getInstance().getNullableAnyType());
962    
963            Call call = CallMaker.makeCallWithExpressions(expression, receiver, null, operationSign, Collections.singletonList(right));
964            ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
965            OverloadResolutionResults<FunctionDescriptor> resolutionResults =
966                    components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorConventions.EQUALS);
967    
968            traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() {
969                @Override
970                public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
971                    // the type of the right expression isn't 'Any?' actually
972                    if (key == right && slice == EXPRESSION_TYPE) return false;
973    
974                    // a hack due to KT-678
975                    // without this line an autocast is reported on the receiver (if it was previously checked for not-null)
976                    // with not-null check the resolution result changes from 'fun Any?.equals' to 'equals' member
977                    if (key == left && slice == AUTOCAST) return false;
978    
979                    return true;
980                }
981            }, true);
982    
983            if (resolutionResults.isSuccess()) {
984                FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
985                if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(), context)) {
986                    ensureNonemptyIntersectionOfOperandTypes(expression, context);
987                }
988            }
989            else {
990                if (resolutionResults.isAmbiguity()) {
991                    context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls()));
992                }
993                else {
994                    context.trace.report(EQUALS_MISSING.on(operationSign));
995                }
996            }
997            return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo);
998        }
999    
1000        @NotNull
1001        private JetTypeInfo visitComparison(
1002                @NotNull JetBinaryExpression expression,
1003                @NotNull ExpressionTypingContext context,
1004                @NotNull JetSimpleNameExpression operationSign
1005        ) {
1006            JetTypeInfo typeInfo = getTypeInfoForBinaryCall(OperatorConventions.COMPARE_TO, context, expression);
1007            DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
1008            JetType compareToReturnType = typeInfo.getType();
1009            JetType type = null;
1010            if (compareToReturnType != null && !compareToReturnType.isError()) {
1011                TypeConstructor constructor = compareToReturnType.getConstructor();
1012                KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
1013                TypeConstructor intTypeConstructor = builtIns.getInt().getTypeConstructor();
1014                if (constructor.equals(intTypeConstructor)) {
1015                    type = builtIns.getBooleanType();
1016                }
1017                else {
1018                    context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType));
1019                }
1020            }
1021            return JetTypeInfo.create(type, dataFlowInfo);
1022        }
1023    
1024        @NotNull
1025        private JetTypeInfo visitBooleanOperationExpression(
1026                @Nullable IElementType operationType,
1027                @Nullable JetExpression left,
1028                @Nullable JetExpression right,
1029                @NotNull ExpressionTypingContext context
1030        ) {
1031            JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
1032            JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context.replaceExpectedType(booleanType), facade);
1033            DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
1034    
1035            WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||");
1036            // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
1037            boolean isAnd = operationType == JetTokens.ANDAND;
1038            DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
1039            WritableScopeImpl rightScope = isAnd ? leftScope : newWritableScopeImpl(context, "Right scope of && or ||");
1040    
1041            ExpressionTypingContext contextForRightExpr =
1042                    context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope).replaceExpectedType(booleanType);
1043            if (right != null) {
1044                facade.getTypeInfo(right, contextForRightExpr);
1045            }
1046            return JetTypeInfo.create(booleanType, dataFlowInfo);
1047        }
1048    
1049        @NotNull
1050        private JetTypeInfo visitElvisExpression(
1051                @NotNull JetBinaryExpression expression,
1052                @NotNull ExpressionTypingContext contextWithExpectedType
1053        ) {
1054            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
1055            JetExpression left = expression.getLeft();
1056            JetExpression right = expression.getRight();
1057    
1058            if (left == null || right == null) {
1059                getTypeInfoOrNullType(left, context, facade);
1060                return JetTypeInfo.create(null, context.dataFlowInfo);
1061            }
1062    
1063            Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Lists.newArrayList(left, right));
1064            ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
1065                    call, "Elvis", Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
1066            JetTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
1067            assert leftTypeInfo != null : "Left expression was not processed: " + expression;
1068            JetType leftType = leftTypeInfo.getType();
1069            if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
1070                context.trace.report(USELESS_ELVIS.on(left, leftType));
1071            }
1072            JetTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext());
1073            assert rightTypeInfo != null : "Right expression was not processed: " + expression;
1074            JetType rightType = rightTypeInfo.getType();
1075    
1076            DataFlowInfo dataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
1077            if (leftType != null && rightType != null && KotlinBuiltIns.getInstance().isNothingOrNullableNothing(rightType) && !rightType.isNullable()) {
1078                DataFlowValue value = DataFlowValueFactory.createDataFlowValue(left, leftType, context.trace.getBindingContext());
1079                dataFlowInfo = dataFlowInfo.disequate(value, DataFlowValue.NULL);
1080            }
1081            JetType type = resolvedCall.getResultingDescriptor().getReturnType();
1082            if (type == null || rightType == null) return JetTypeInfo.create(null, dataFlowInfo);
1083    
1084            return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified(type, rightType.isNullable()), dataFlowInfo);
1085        }
1086    
1087        @NotNull
1088        public JetTypeInfo checkInExpression(
1089                @NotNull JetElement callElement,
1090                @NotNull JetSimpleNameExpression operationSign,
1091                @NotNull ValueArgument leftArgument,
1092                @Nullable JetExpression right,
1093                @NotNull ExpressionTypingContext context
1094        ) {
1095            JetExpression left = leftArgument.getArgumentExpression();
1096            ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
1097            if (right == null) {
1098                if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
1099                return JetTypeInfo.create(null, context.dataFlowInfo);
1100            }
1101    
1102            DataFlowInfo dataFlowInfo = facade.getTypeInfo(right, contextWithNoExpectedType).getDataFlowInfo();
1103    
1104            ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, contextWithNoExpectedType);
1105            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1106    
1107            OverloadResolutionResults<FunctionDescriptor> resolutionResult = components.callResolver.resolveCallWithGivenName(
1108                    contextWithDataFlow,
1109                    CallMaker.makeCall(callElement, receiver, null, operationSign, Collections.singletonList(leftArgument)),
1110                    operationSign,
1111                    OperatorConventions.CONTAINS);
1112            JetType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
1113            ensureBooleanResult(operationSign, OperatorConventions.CONTAINS, containsType, context);
1114    
1115            if (left != null) {
1116                dataFlowInfo = facade.getTypeInfo(left, contextWithDataFlow).getDataFlowInfo().and(dataFlowInfo);
1117            }
1118    
1119            return JetTypeInfo.create(resolutionResult.isSuccess() ? KotlinBuiltIns.getInstance().getBooleanType() : null, dataFlowInfo);
1120        }
1121    
1122        private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
1123            JetExpression left = expression.getLeft();
1124            if (left == null) return;
1125    
1126            JetExpression right = expression.getRight();
1127    
1128            // TODO : duplicated effort for == and !=
1129            JetType leftType = facade.getTypeInfo(left, context).getType();
1130            if (leftType != null && right != null) {
1131                JetType rightType = facade.getTypeInfo(right, context).getType();
1132    
1133                if (rightType != null) {
1134                    if (TypeUtils.isIntersectionEmpty(leftType, rightType)) {
1135                        context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType));
1136                    }
1137                    checkSenselessComparisonWithNull(expression, left, right, context);
1138                }
1139            }
1140        }
1141    
1142        private void checkSenselessComparisonWithNull(@NotNull JetBinaryExpression expression, @NotNull JetExpression left, @NotNull JetExpression right, @NotNull ExpressionTypingContext context) {
1143            JetExpression expr;
1144            if (JetPsiUtil.isNullConstant(left)) {
1145                expr = right;
1146            }
1147            else if (JetPsiUtil.isNullConstant(right)) {
1148                expr = left;
1149            }
1150            else return;
1151    
1152            JetSimpleNameExpression operationSign = expression.getOperationReference();
1153            JetType type = facade.getTypeInfo(expr, context).getType();
1154            if (type == null || type.isError()) return;
1155    
1156            DataFlowValue value = DataFlowValueFactory.createDataFlowValue(expr, type, context.trace.getBindingContext());
1157            Nullability nullability = context.dataFlowInfo.getNullability(value);
1158    
1159            boolean expressionIsAlways;
1160            boolean equality = operationSign.getReferencedNameElementType() == JetTokens.EQEQ || operationSign.getReferencedNameElementType() == JetTokens.EQEQEQ;
1161    
1162            if (nullability == Nullability.NULL) {
1163                expressionIsAlways = equality;
1164            }
1165            else if (nullability == Nullability.NOT_NULL) {
1166                expressionIsAlways = !equality;
1167            }
1168            else return;
1169    
1170            context.trace.report(SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways));
1171        }
1172    
1173        @NotNull
1174        private JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
1175            return assignmentIsNotAnExpressionError(expression, context);
1176        }
1177    
1178        @NotNull
1179        private JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
1180            return assignmentIsNotAnExpressionError(expression, context);
1181        }
1182    
1183        @NotNull
1184        private JetTypeInfo assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
1185            facade.checkStatementType(expression, context);
1186            context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
1187            return JetTypeInfo.create(null, context.dataFlowInfo);
1188        }
1189    
1190        @Override
1191        public JetTypeInfo visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, ExpressionTypingContext context) {
1192            JetTypeInfo typeInfo = resolveArrayAccessGetMethod(expression, context);
1193            return DataFlowUtils.checkType(typeInfo, expression, context);
1194        }
1195    
1196        @NotNull
1197        public JetTypeInfo getTypeInfoForBinaryCall(
1198                @NotNull Name name,
1199                @NotNull ExpressionTypingContext context,
1200                @NotNull JetBinaryExpression binaryExpression
1201        ) {
1202            JetExpression left = binaryExpression.getLeft();
1203            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
1204            if (left != null) {
1205                //left here is a receiver, so it doesn't depend on expected type
1206                dataFlowInfo = facade.getTypeInfo(
1207                        left, context.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
1208            }
1209            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1210    
1211            OverloadResolutionResults<FunctionDescriptor> resolutionResults;
1212            if (left != null) {
1213                ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
1214                resolutionResults = components.callResolver.resolveBinaryCall(
1215                        contextWithDataFlow.replaceScope(context.scope),
1216                        receiver, binaryExpression, name
1217                );
1218            }
1219            else {
1220                resolutionResults = OverloadResolutionResultsImpl.nameNotFound();
1221            }
1222    
1223            if (resolutionResults.isSingleResult()) {
1224                dataFlowInfo = resolutionResults.getResultingCall().getDataFlowInfoForArguments().getResultInfo();
1225            }
1226    
1227            return JetTypeInfo.create(OverloadResolutionResultsUtil.getResultingType(resolutionResults, context.contextDependency), dataFlowInfo);
1228        }
1229    
1230        @Override
1231        public JetTypeInfo visitDeclaration(@NotNull JetDeclaration dcl, ExpressionTypingContext context) {
1232            context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl));
1233            return JetTypeInfo.create(null, context.dataFlowInfo);
1234        }
1235    
1236        @Override
1237        public JetTypeInfo visitRootPackageExpression(@NotNull JetRootPackageExpression expression, ExpressionTypingContext context) {
1238            if (!JetPsiUtil.isLHSOfDot(expression)) {
1239                context.trace.report(PACKAGE_IS_NOT_AN_EXPRESSION.on(expression));
1240            }
1241            return JetTypeInfo.create(null, context.dataFlowInfo);
1242        }
1243    
1244    
1245        @Override
1246        public JetTypeInfo visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
1247            final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
1248            final DataFlowInfo[] dataFlowInfo = new DataFlowInfo[] { context.dataFlowInfo };
1249            for (JetStringTemplateEntry entry : expression.getEntries()) {
1250                entry.accept(new JetVisitorVoid() {
1251    
1252                    @Override
1253                    public void visitStringTemplateEntryWithExpression(@NotNull JetStringTemplateEntryWithExpression entry) {
1254                        JetExpression entryExpression = entry.getExpression();
1255                        if (entryExpression != null) {
1256                            JetTypeInfo typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(dataFlowInfo[0]));
1257                            dataFlowInfo[0] = typeInfo.getDataFlowInfo();
1258                        }
1259                    }
1260    
1261                    @Override
1262                    public void visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry) {
1263                        CompileTimeConstantChecker.CharacterWithDiagnostic value = CompileTimeConstantChecker.escapedStringToCharacter(entry.getText(), entry);
1264                        Diagnostic diagnostic = value.getDiagnostic();
1265                        if (diagnostic != null) {
1266                            context.trace.report(diagnostic);
1267                        }
1268                    }
1269                });
1270            }
1271            ConstantExpressionEvaluator.OBJECT$.evaluate(expression, context.trace, contextWithExpectedType.expectedType);
1272            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getStringType(), expression, contextWithExpectedType, dataFlowInfo[0]);
1273        }
1274    
1275        @Override
1276        public JetTypeInfo visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression, ExpressionTypingContext context) {
1277            return visitAnnotatedExpression(expression, context, false);
1278        }
1279    
1280        public JetTypeInfo visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
1281            components.expressionTypingServices.getAnnotationResolver().resolveAnnotationsWithArguments(
1282                    context.scope, expression.getAnnotationEntries(), context.trace);
1283    
1284            JetExpression baseExpression = expression.getBaseExpression();
1285            if (baseExpression == null) {
1286                return JetTypeInfo.create(null, context.dataFlowInfo);
1287            }
1288            return facade.getTypeInfo(baseExpression, context, isStatement);
1289        }
1290    
1291        @Override
1292        public JetTypeInfo visitJetElement(@NotNull JetElement element, ExpressionTypingContext context) {
1293            context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
1294            return JetTypeInfo.create(null, context.dataFlowInfo);
1295        }
1296    
1297        @NotNull
1298            /*package*/ JetTypeInfo resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) {
1299            return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
1300        }
1301    
1302        @NotNull
1303            /*package*/ JetTypeInfo resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) {
1304            return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
1305        }
1306    
1307        @NotNull
1308        private JetTypeInfo resolveArrayAccessSpecialMethod(@NotNull JetArrayAccessExpression arrayAccessExpression,
1309                                                        @Nullable JetExpression rightHandSide, //only for 'set' method
1310                                                        @NotNull ExpressionTypingContext oldContext,
1311                                                        @NotNull BindingTrace traceForResolveResult,
1312                                                        boolean isGet) {
1313            JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
1314            if (arrayExpression == null) return JetTypeInfo.create(null, oldContext.dataFlowInfo);
1315    
1316            JetTypeInfo arrayTypeInfo = facade.safeGetTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
1317                    .replaceContextDependency(INDEPENDENT));
1318            JetType arrayType = ExpressionTypingUtils.safeGetType(arrayTypeInfo);
1319    
1320            DataFlowInfo dataFlowInfo = arrayTypeInfo.getDataFlowInfo();
1321            ExpressionTypingContext context = oldContext.replaceDataFlowInfo(dataFlowInfo);
1322            ExpressionReceiver receiver = new ExpressionReceiver(arrayExpression, arrayType);
1323            if (!isGet) assert rightHandSide != null;
1324    
1325            Call call = isGet
1326                        ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD)
1327                        : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD);
1328            OverloadResolutionResults<FunctionDescriptor> functionResults = components.callResolver.resolveCallWithGivenName(
1329                    context, call, arrayAccessExpression, Name.identifier(isGet ? "get" : "set"));
1330    
1331            List<JetExpression> indices = arrayAccessExpression.getIndexExpressions();
1332            // The accumulated data flow info of all index expressions is saved on the last index
1333            if (!indices.isEmpty()) {
1334                dataFlowInfo = facade.getTypeInfo(indices.get(indices.size() - 1), context).getDataFlowInfo();
1335            }
1336    
1337            if (!isGet) {
1338                dataFlowInfo = facade.getTypeInfo(rightHandSide, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
1339            }
1340    
1341            if (!functionResults.isSingleResult()) {
1342                traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression));
1343                return JetTypeInfo.create(null, dataFlowInfo);
1344            }
1345            traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall());
1346            return JetTypeInfo.create(functionResults.getResultingDescriptor().getReturnType(), dataFlowInfo);
1347        }
1348    }