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            ReceiverValue receiver = new TransientReceiver(lhsType);
595            TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
596                    context, "trace to resolve callable reference with receiver", reference);
597            CallableDescriptor descriptor = resolveCallableNotCheckingArguments(
598                    reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
599            if (result[0]) {
600                temporaryWithReceiver.commit();
601                return descriptor;
602            }
603    
604            JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier);
605            TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
606                    context, "trace to resolve callable reference in static scope", reference);
607            CallableDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
608                    context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
609            if (result[0]) {
610                temporaryForStatic.commit();
611                return possibleStaticNestedClassConstructor;
612            }
613    
614            return null;
615        }
616    
617        @Nullable
618        private CallableDescriptor resolveCallableNotCheckingArguments(
619                @NotNull JetSimpleNameExpression reference,
620                @NotNull ReceiverValue receiver,
621                @NotNull ExpressionTypingContext context,
622                @NotNull boolean[] result
623        ) {
624            Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
625    
626            TemporaryTraceAndCache funTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as function",
627                                                                            reference);
628            ResolvedCall<FunctionDescriptor> function = components.expressionTypingServices.getCallExpressionResolver()
629                    .getResolvedCallForFunction(call, reference, context.replaceTraceAndCache(funTrace).replaceExpectedType(NO_EXPECTED_TYPE),
630                                                CheckValueArgumentsMode.DISABLED, result);
631            if (result[0]) {
632                funTrace.commit();
633    
634                if (function instanceof VariableAsFunctionResolvedCall) {
635                    context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
636                    return null;
637                }
638    
639                return function != null ? function.getResultingDescriptor() : null;
640            }
641    
642            TemporaryTraceAndCache varTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as variable",
643                                                                            reference);
644            OverloadResolutionResults<VariableDescriptor> variableResults =
645                    components.expressionTypingServices.getCallResolver().resolveSimpleProperty(
646                            BasicCallResolutionContext.create(context.replaceTraceAndCache(varTrace).replaceExpectedType(NO_EXPECTED_TYPE),
647                                                              call, CheckValueArgumentsMode.DISABLED)
648                    );
649            if (!variableResults.isNothing()) {
650                ResolvedCall<VariableDescriptor> variable =
651                        OverloadResolutionResultsUtil.getResultingCall(variableResults, context.contextDependency);
652    
653                varTrace.commit();
654                if (variable != null) {
655                    result[0] = true;
656                    return variable.getResultingDescriptor();
657                }
658            }
659    
660            return null;
661        }
662    
663        @Override
664        public JetTypeInfo visitQualifiedExpression(@NotNull JetQualifiedExpression expression, ExpressionTypingContext context) {
665            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
666            return callExpressionResolver.getQualifiedExpressionTypeInfo(expression, context);
667        }
668    
669        @Override
670        public JetTypeInfo visitCallExpression(@NotNull JetCallExpression expression, ExpressionTypingContext context) {
671            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
672            return callExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context);
673        }
674    
675        @Override
676        public JetTypeInfo visitUnaryExpression(@NotNull JetUnaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
677            ExpressionTypingContext context = isUnaryExpressionDependentOnExpectedType(expression)
678                    ? contextWithExpectedType
679                    : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
680    
681            JetExpression baseExpression = expression.getBaseExpression();
682            if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
683    
684            JetSimpleNameExpression operationSign = expression.getOperationReference();
685    
686            IElementType operationType = operationSign.getReferencedNameElementType();
687    
688            // Special case for expr!!
689            if (operationType == JetTokens.EXCLEXCL) {
690                return visitExclExclExpression(expression, context);
691            }
692    
693            // Type check the base expression
694            JetTypeInfo typeInfo = facade.safeGetTypeInfo(baseExpression, context);
695            JetType type = ExpressionTypingUtils.safeGetType(typeInfo);
696            ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type);
697    
698            Call call = CallMaker.makeCall(receiver, expression);
699            DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
700    
701            // Conventions for unary operations
702            Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
703            if (name == null) {
704                context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
705                return JetTypeInfo.create(null, dataFlowInfo);
706            }
707    
708            // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
709            if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) {
710                JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
711                TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace
712                        .create(context.trace, "trace to resolve array access set method for unary expression", expression);
713                ExpressionTypingContext newContext = context.replaceBindingTrace(temporaryBindingTrace);
714                resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression, stubExpression, newContext, context.trace);
715            }
716    
717            // Resolve the operation reference
718            OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(
719                    context, call, expression.getOperationReference(), name);
720    
721            if (!resolutionResults.isSuccess()) {
722                return JetTypeInfo.create(null, dataFlowInfo);
723            }
724    
725            // Computing the return type
726            JetType returnType = resolutionResults.getResultingDescriptor().getReturnType();
727            JetType result;
728            if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
729                assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
730                if (KotlinBuiltIns.getInstance().isUnit(returnType)) {
731                    result = ErrorUtils.createErrorType(KotlinBuiltIns.getInstance().getUnit().getName().asString());
732                    context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
733                }
734                else {
735                    JetType receiverType = receiver.getType();
736                    if (!JetTypeChecker.DEFAULT.isSubtypeOf(returnType, receiverType)) {
737                        context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
738                    }
739                    else {
740                        context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
741    
742                        checkLValue(context.trace, baseExpression);
743                    }
744                    // TODO : Maybe returnType?
745                    result = receiverType;
746                }
747            }
748            else {
749                result = returnType;
750            }
751    
752            CompileTimeConstant<?> value = ConstantExpressionEvaluator.OBJECT$.evaluate(expression, contextWithExpectedType.trace,
753                                                                                        contextWithExpectedType.expectedType);
754            if (value != null) {
755                return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
756            }
757    
758            return DataFlowUtils.checkType(result, expression, contextWithExpectedType, dataFlowInfo);
759        }
760    
761        @NotNull
762        public static JetTypeInfo createCompileTimeConstantTypeInfo(
763                @NotNull CompileTimeConstant<?> value,
764                @NotNull JetExpression expression,
765                @NotNull ExpressionTypingContext context
766        ) {
767            JetType expressionType = value.getType(KotlinBuiltIns.getInstance());
768            if (value instanceof IntegerValueTypeConstant && context.contextDependency == INDEPENDENT) {
769                expressionType = ((IntegerValueTypeConstant) value).getType(context.expectedType);
770                ArgumentTypeResolver.updateNumberType(expressionType, expression, context.trace);
771            }
772    
773            return DataFlowUtils.checkType(expressionType, expression, context, context.dataFlowInfo);
774        }
775    
776        private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) {
777            JetExpression baseExpression = expression.getBaseExpression();
778            assert baseExpression != null;
779            JetSimpleNameExpression operationSign = expression.getOperationReference();
780            assert operationSign.getReferencedNameElementType() == JetTokens.EXCLEXCL;
781    
782            Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Collections.singletonList(baseExpression));
783            components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
784                    call, "ExclExcl", Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null);
785            JetTypeInfo baseTypeInfo = BindingContextUtils.getRecordedTypeInfo(baseExpression, context.trace.getBindingContext());
786            assert baseTypeInfo != null : "Base expression was not processed: " + expression;
787            JetType baseType = baseTypeInfo.getType();
788            if (baseType == null) {
789                return baseTypeInfo;
790            }
791            DataFlowInfo dataFlowInfo = baseTypeInfo.getDataFlowInfo();
792            if (isKnownToBeNotNull(baseExpression, context) && !baseType.isError()) {
793                context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, baseType));
794            }
795            else {
796                DataFlowValue value = DataFlowValueFactory.createDataFlowValue(baseExpression, baseType, context.trace.getBindingContext());
797                dataFlowInfo = dataFlowInfo.disequate(value, DataFlowValue.NULL);
798            }
799            return JetTypeInfo.create(TypeUtils.makeNotNullable(baseType), dataFlowInfo);
800        }
801    
802        @Override
803        public JetTypeInfo visitLabeledExpression(
804                @NotNull JetLabeledExpression expression, ExpressionTypingContext context
805        ) {
806            return visitLabeledExpression(expression, context, false);
807        }
808    
809        @NotNull
810        public JetTypeInfo visitLabeledExpression(
811                @NotNull JetLabeledExpression expression,
812                @NotNull ExpressionTypingContext context,
813                boolean isStatement
814        ) {
815            JetExpression baseExpression = expression.getBaseExpression();
816            if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
817    
818            return facade.getTypeInfo(baseExpression, context, isStatement);
819        }
820    
821        private static boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) {
822            JetType type = context.trace.get(EXPRESSION_TYPE, expression);
823            assert type != null : "This method is only supposed to be called when the type is not null";
824            return isKnownToBeNotNull(expression, type, context);
825        }
826    
827        private static boolean isKnownToBeNotNull(JetExpression expression, JetType jetType, ExpressionTypingContext context) {
828            DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, jetType, context.trace.getBindingContext());
829            return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull();
830        }
831    
832        public static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) {
833            checkLValue(trace, expression, false);
834        }
835    
836        private static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expressionWithParenthesis, boolean canBeThis) {
837            JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
838            if (expression instanceof JetArrayAccessExpression) {
839                JetExpression arrayExpression = ((JetArrayAccessExpression) expression).getArrayExpression();
840                if (arrayExpression != null) {
841                    checkLValue(trace, arrayExpression, true);
842                }
843                return;
844            }
845            if (canBeThis && expression instanceof JetThisExpression) return;
846            VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
847    
848            JetExpression reportOn = expression != null ? expression : expressionWithParenthesis;
849            if (variable instanceof PropertyDescriptor) {
850                PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
851                if (propertyDescriptor.isSetterProjectedOut()) {
852                    trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
853                }
854            }
855    
856            if (variable == null) {
857                trace.report(VARIABLE_EXPECTED.on(reportOn));
858            }
859        }
860    
861        @Override
862        public JetTypeInfo visitBinaryExpression(@NotNull JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
863            ExpressionTypingContext context = isBinaryExpressionDependentOnExpectedType(expression)
864                    ? contextWithExpectedType
865                    : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
866    
867            JetSimpleNameExpression operationSign = expression.getOperationReference();
868            JetExpression left = expression.getLeft();
869            JetExpression right = expression.getRight();
870            IElementType operationType = operationSign.getReferencedNameElementType();
871    
872            JetTypeInfo result;
873    
874            //Expressions that can depend on expected type
875            if (operationType == JetTokens.IDENTIFIER) {
876                Name referencedName = operationSign.getReferencedNameAsName();
877                result = getTypeInfoForBinaryCall(referencedName, context, expression);
878            }
879            else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) {
880                Name referencedName = OperatorConventions.BINARY_OPERATION_NAMES.get(operationType);
881                result = getTypeInfoForBinaryCall(referencedName, context, expression);
882            }
883            else if (operationType == JetTokens.ELVIS) {
884                //base expression of elvis operator is checked for 'type mismatch', so the whole expression shouldn't be checked
885                return visitElvisExpression(expression, context);
886            }
887    
888            //Expressions that don't depend on expected type
889            else if (operationType == JetTokens.EQ) {
890                result = visitAssignment(expression, context);
891            }
892            else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
893                result = visitAssignmentOperation(expression, context);
894            }
895            else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
896                result = visitComparison(expression, context, operationSign);
897            }
898            else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
899                result = visitEquality(expression, context, operationSign, left, right);
900            }
901            else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
902                ensureNonemptyIntersectionOfOperandTypes(expression, context);
903                // TODO : Check comparison pointlessness
904                result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), context.dataFlowInfo);
905            }
906            else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
907                ValueArgument leftArgument = CallMaker.makeValueArgument(left, left != null ? left : operationSign);
908                result = checkInExpression(expression, operationSign, leftArgument, right, context);
909            }
910            else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
911                result = visitBooleanOperationExpression(operationType, left, right, context);
912            }
913            else {
914                context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
915                result = JetTypeInfo.create(null, context.dataFlowInfo);
916            }
917            CompileTimeConstant<?> value = ConstantExpressionEvaluator.OBJECT$.
918                    evaluate(expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType);
919            if (value != null) {
920                return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
921            }
922            return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
923        }
924    
925        private JetTypeInfo visitEquality(
926                JetBinaryExpression expression,
927                ExpressionTypingContext context,
928                JetSimpleNameExpression operationSign,
929                final JetExpression left,
930                final JetExpression right
931        ) {
932            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
933            if (right == null || left == null) {
934                ExpressionTypingUtils.getTypeInfoOrNullType(right, context, facade);
935                ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
936                return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo);
937            }
938            ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context);
939    
940            JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
941    
942            dataFlowInfo = leftTypeInfo.getDataFlowInfo();
943            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
944    
945            JetTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithDataFlow);
946            dataFlowInfo = rightTypeInfo.getDataFlowInfo();
947    
948            TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create(
949                    context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
950            traceInterpretingRightAsNullableAny.record(EXPRESSION_TYPE, right, KotlinBuiltIns.getInstance().getNullableAnyType());
951    
952            Call call = CallMaker.makeCallWithExpressions(expression, receiver, null, operationSign, Collections.singletonList(right));
953            ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
954            OverloadResolutionResults<FunctionDescriptor> resolutionResults =
955                    components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorConventions.EQUALS);
956    
957            traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() {
958                @Override
959                public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
960                    // the type of the right expression isn't 'Any?' actually
961                    if (key == right && slice == EXPRESSION_TYPE) return false;
962    
963                    // a hack due to KT-678
964                    // without this line an autocast is reported on the receiver (if it was previously checked for not-null)
965                    // with not-null check the resolution result changes from 'fun Any?.equals' to 'equals' member
966                    if (key == left && slice == AUTOCAST) return false;
967    
968                    return true;
969                }
970            }, true);
971    
972            if (resolutionResults.isSuccess()) {
973                FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
974                if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(), context)) {
975                    ensureNonemptyIntersectionOfOperandTypes(expression, context);
976                }
977            }
978            else {
979                if (resolutionResults.isAmbiguity()) {
980                    context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls()));
981                }
982                else {
983                    context.trace.report(EQUALS_MISSING.on(operationSign));
984                }
985            }
986            return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo);
987        }
988    
989        @NotNull
990        private JetTypeInfo visitComparison(
991                @NotNull JetBinaryExpression expression,
992                @NotNull ExpressionTypingContext context,
993                @NotNull JetSimpleNameExpression operationSign
994        ) {
995            JetTypeInfo typeInfo = getTypeInfoForBinaryCall(OperatorConventions.COMPARE_TO, context, expression);
996            DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
997            JetType compareToReturnType = typeInfo.getType();
998            JetType type = null;
999            if (compareToReturnType != null && !compareToReturnType.isError()) {
1000                TypeConstructor constructor = compareToReturnType.getConstructor();
1001                KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
1002                TypeConstructor intTypeConstructor = builtIns.getInt().getTypeConstructor();
1003                if (constructor.equals(intTypeConstructor)) {
1004                    type = builtIns.getBooleanType();
1005                }
1006                else {
1007                    context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType));
1008                }
1009            }
1010            return JetTypeInfo.create(type, dataFlowInfo);
1011        }
1012    
1013        @NotNull
1014        private JetTypeInfo visitBooleanOperationExpression(
1015                @Nullable IElementType operationType,
1016                @Nullable JetExpression left,
1017                @Nullable JetExpression right,
1018                @NotNull ExpressionTypingContext context
1019        ) {
1020            JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
1021            JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context.replaceExpectedType(booleanType), facade);
1022            DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
1023    
1024            WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||");
1025            // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
1026            boolean isAnd = operationType == JetTokens.ANDAND;
1027            DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
1028            WritableScopeImpl rightScope = isAnd ? leftScope : newWritableScopeImpl(context, "Right scope of && or ||");
1029    
1030            ExpressionTypingContext contextForRightExpr =
1031                    context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope).replaceExpectedType(booleanType);
1032            if (right != null) {
1033                facade.getTypeInfo(right, contextForRightExpr);
1034            }
1035            return JetTypeInfo.create(booleanType, dataFlowInfo);
1036        }
1037    
1038        @NotNull
1039        private JetTypeInfo visitElvisExpression(
1040                @NotNull JetBinaryExpression expression,
1041                @NotNull ExpressionTypingContext contextWithExpectedType
1042        ) {
1043            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
1044            JetExpression left = expression.getLeft();
1045            JetExpression right = expression.getRight();
1046    
1047            if (left == null || right == null) {
1048                getTypeInfoOrNullType(left, context, facade);
1049                return JetTypeInfo.create(null, context.dataFlowInfo);
1050            }
1051    
1052            Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Lists.newArrayList(left, right));
1053            ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
1054                    call, "Elvis", Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
1055            JetTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
1056            assert leftTypeInfo != null : "Left expression was not processed: " + expression;
1057            JetType leftType = leftTypeInfo.getType();
1058            if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
1059                context.trace.report(USELESS_ELVIS.on(left, leftType));
1060            }
1061            JetTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext());
1062            assert rightTypeInfo != null : "Right expression was not processed: " + expression;
1063            JetType rightType = rightTypeInfo.getType();
1064    
1065            DataFlowInfo dataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
1066            JetType type = resolvedCall.getResultingDescriptor().getReturnType();
1067            if (type == null || rightType == null) return JetTypeInfo.create(null, dataFlowInfo);
1068    
1069            return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified(type, rightType.isNullable()), dataFlowInfo);
1070        }
1071    
1072        @NotNull
1073        public JetTypeInfo checkInExpression(
1074                @NotNull JetElement callElement,
1075                @NotNull JetSimpleNameExpression operationSign,
1076                @NotNull ValueArgument leftArgument,
1077                @Nullable JetExpression right,
1078                @NotNull ExpressionTypingContext context
1079        ) {
1080            JetExpression left = leftArgument.getArgumentExpression();
1081            ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
1082            if (right == null) {
1083                if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
1084                return JetTypeInfo.create(null, context.dataFlowInfo);
1085            }
1086    
1087            DataFlowInfo dataFlowInfo = facade.getTypeInfo(right, contextWithNoExpectedType).getDataFlowInfo();
1088    
1089            ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, contextWithNoExpectedType);
1090            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1091    
1092            OverloadResolutionResults<FunctionDescriptor> resolutionResult = components.callResolver.resolveCallWithGivenName(
1093                    contextWithDataFlow,
1094                    CallMaker.makeCall(callElement, receiver, null, operationSign, Collections.singletonList(leftArgument)),
1095                    operationSign,
1096                    OperatorConventions.CONTAINS);
1097            JetType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
1098            ensureBooleanResult(operationSign, OperatorConventions.CONTAINS, containsType, context);
1099    
1100            if (left != null) {
1101                dataFlowInfo = facade.getTypeInfo(left, contextWithDataFlow).getDataFlowInfo().and(dataFlowInfo);
1102            }
1103    
1104            return JetTypeInfo.create(resolutionResult.isSuccess() ? KotlinBuiltIns.getInstance().getBooleanType() : null, dataFlowInfo);
1105        }
1106    
1107        private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
1108            JetExpression left = expression.getLeft();
1109            if (left == null) return;
1110    
1111            JetExpression right = expression.getRight();
1112    
1113            // TODO : duplicated effort for == and !=
1114            JetType leftType = facade.getTypeInfo(left, context).getType();
1115            if (leftType != null && right != null) {
1116                JetType rightType = facade.getTypeInfo(right, context).getType();
1117    
1118                if (rightType != null) {
1119                    if (TypeUtils.isIntersectionEmpty(leftType, rightType)) {
1120                        context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType));
1121                    }
1122                    checkSenselessComparisonWithNull(expression, left, right, context);
1123                }
1124            }
1125        }
1126    
1127        private void checkSenselessComparisonWithNull(@NotNull JetBinaryExpression expression, @NotNull JetExpression left, @NotNull JetExpression right, @NotNull ExpressionTypingContext context) {
1128            JetExpression expr;
1129            if (JetPsiUtil.isNullConstant(left)) {
1130                expr = right;
1131            }
1132            else if (JetPsiUtil.isNullConstant(right)) {
1133                expr = left;
1134            }
1135            else return;
1136    
1137            JetSimpleNameExpression operationSign = expression.getOperationReference();
1138            JetType type = facade.getTypeInfo(expr, context).getType();
1139            if (type == null || type.isError()) return;
1140    
1141            DataFlowValue value = DataFlowValueFactory.createDataFlowValue(expr, type, context.trace.getBindingContext());
1142            Nullability nullability = context.dataFlowInfo.getNullability(value);
1143    
1144            boolean expressionIsAlways;
1145            boolean equality = operationSign.getReferencedNameElementType() == JetTokens.EQEQ || operationSign.getReferencedNameElementType() == JetTokens.EQEQEQ;
1146    
1147            if (nullability == Nullability.NULL) {
1148                expressionIsAlways = equality;
1149            }
1150            else if (nullability == Nullability.NOT_NULL) {
1151                expressionIsAlways = !equality;
1152            }
1153            else return;
1154    
1155            context.trace.report(SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways));
1156        }
1157    
1158        @NotNull
1159        private JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
1160            return assignmentIsNotAnExpressionError(expression, context);
1161        }
1162    
1163        @NotNull
1164        private JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
1165            return assignmentIsNotAnExpressionError(expression, context);
1166        }
1167    
1168        @NotNull
1169        private JetTypeInfo assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
1170            facade.checkStatementType(expression, context);
1171            context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
1172            return JetTypeInfo.create(null, context.dataFlowInfo);
1173        }
1174    
1175        @Override
1176        public JetTypeInfo visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, ExpressionTypingContext context) {
1177            JetTypeInfo typeInfo = resolveArrayAccessGetMethod(expression, context);
1178            return DataFlowUtils.checkType(typeInfo, expression, context);
1179        }
1180    
1181        @NotNull
1182        public JetTypeInfo getTypeInfoForBinaryCall(
1183                @NotNull Name name,
1184                @NotNull ExpressionTypingContext context,
1185                @NotNull JetBinaryExpression binaryExpression
1186        ) {
1187            JetExpression left = binaryExpression.getLeft();
1188            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
1189            if (left != null) {
1190                //left here is a receiver, so it doesn't depend on expected type
1191                dataFlowInfo = facade.getTypeInfo(
1192                        left, context.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
1193            }
1194            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1195    
1196            OverloadResolutionResults<FunctionDescriptor> resolutionResults;
1197            if (left != null) {
1198                ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
1199                resolutionResults = components.callResolver.resolveBinaryCall(
1200                        contextWithDataFlow.replaceScope(context.scope),
1201                        receiver, binaryExpression, name
1202                );
1203            }
1204            else {
1205                resolutionResults = OverloadResolutionResultsImpl.nameNotFound();
1206            }
1207    
1208            if (resolutionResults.isSingleResult()) {
1209                dataFlowInfo = resolutionResults.getResultingCall().getDataFlowInfoForArguments().getResultInfo();
1210            }
1211    
1212            return JetTypeInfo.create(OverloadResolutionResultsUtil.getResultingType(resolutionResults, context.contextDependency), dataFlowInfo);
1213        }
1214    
1215        @Override
1216        public JetTypeInfo visitDeclaration(@NotNull JetDeclaration dcl, ExpressionTypingContext context) {
1217            context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl));
1218            return JetTypeInfo.create(null, context.dataFlowInfo);
1219        }
1220    
1221        @Override
1222        public JetTypeInfo visitRootPackageExpression(@NotNull JetRootPackageExpression expression, ExpressionTypingContext context) {
1223            if (JetPsiUtil.isLHSOfDot(expression)) {
1224                return DataFlowUtils.checkType(JetModuleUtil.getRootPackageType(expression), expression, context, context.dataFlowInfo);
1225            }
1226            context.trace.report(PACKAGE_IS_NOT_AN_EXPRESSION.on(expression));
1227            return JetTypeInfo.create(null, context.dataFlowInfo);
1228        }
1229    
1230    
1231        @Override
1232        public JetTypeInfo visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
1233            final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
1234            final DataFlowInfo[] dataFlowInfo = new DataFlowInfo[] { context.dataFlowInfo };
1235            for (JetStringTemplateEntry entry : expression.getEntries()) {
1236                entry.accept(new JetVisitorVoid() {
1237    
1238                    @Override
1239                    public void visitStringTemplateEntryWithExpression(@NotNull JetStringTemplateEntryWithExpression entry) {
1240                        JetExpression entryExpression = entry.getExpression();
1241                        if (entryExpression != null) {
1242                            JetTypeInfo typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(dataFlowInfo[0]));
1243                            dataFlowInfo[0] = typeInfo.getDataFlowInfo();
1244                        }
1245                    }
1246    
1247                    @Override
1248                    public void visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry) {
1249                        CompileTimeConstantChecker.CharacterWithDiagnostic value = CompileTimeConstantChecker.escapedStringToCharacter(entry.getText(), entry);
1250                        Diagnostic diagnostic = value.getDiagnostic();
1251                        if (diagnostic != null) {
1252                            context.trace.report(diagnostic);
1253                        }
1254                    }
1255                });
1256            }
1257            ConstantExpressionEvaluator.OBJECT$.evaluate(expression, context.trace, contextWithExpectedType.expectedType);
1258            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getStringType(), expression, contextWithExpectedType, dataFlowInfo[0]);
1259        }
1260    
1261        @Override
1262        public JetTypeInfo visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression, ExpressionTypingContext context) {
1263            return visitAnnotatedExpression(expression, context, false);
1264        }
1265    
1266        public JetTypeInfo visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
1267            components.expressionTypingServices.getAnnotationResolver().resolveAnnotationsWithArguments(
1268                    context.scope, expression.getAnnotationEntries(), context.trace);
1269    
1270            JetExpression baseExpression = expression.getBaseExpression();
1271            if (baseExpression == null) {
1272                return JetTypeInfo.create(null, context.dataFlowInfo);
1273            }
1274            return facade.getTypeInfo(baseExpression, context, isStatement);
1275        }
1276    
1277        @Override
1278        public JetTypeInfo visitJetElement(@NotNull JetElement element, ExpressionTypingContext context) {
1279            context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
1280            return JetTypeInfo.create(null, context.dataFlowInfo);
1281        }
1282    
1283        @NotNull
1284            /*package*/ JetTypeInfo resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) {
1285            return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
1286        }
1287    
1288        @NotNull
1289            /*package*/ JetTypeInfo resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) {
1290            return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
1291        }
1292    
1293        @NotNull
1294        private JetTypeInfo resolveArrayAccessSpecialMethod(@NotNull JetArrayAccessExpression arrayAccessExpression,
1295                                                        @Nullable JetExpression rightHandSide, //only for 'set' method
1296                                                        @NotNull ExpressionTypingContext oldContext,
1297                                                        @NotNull BindingTrace traceForResolveResult,
1298                                                        boolean isGet) {
1299            JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
1300            if (arrayExpression == null) return JetTypeInfo.create(null, oldContext.dataFlowInfo);
1301    
1302            JetTypeInfo arrayTypeInfo = facade.safeGetTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
1303                    .replaceContextDependency(INDEPENDENT));
1304            JetType arrayType = ExpressionTypingUtils.safeGetType(arrayTypeInfo);
1305    
1306            DataFlowInfo dataFlowInfo = arrayTypeInfo.getDataFlowInfo();
1307            ExpressionTypingContext context = oldContext.replaceDataFlowInfo(dataFlowInfo);
1308            ExpressionReceiver receiver = new ExpressionReceiver(arrayExpression, arrayType);
1309            if (!isGet) assert rightHandSide != null;
1310    
1311            Call call = isGet
1312                        ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD)
1313                        : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD);
1314            OverloadResolutionResults<FunctionDescriptor> functionResults = components.callResolver.resolveCallWithGivenName(
1315                    context, call, arrayAccessExpression, Name.identifier(isGet ? "get" : "set"));
1316    
1317            List<JetExpression> indices = arrayAccessExpression.getIndexExpressions();
1318            // The accumulated data flow info of all index expressions is saved on the last index
1319            if (!indices.isEmpty()) {
1320                dataFlowInfo = facade.getTypeInfo(indices.get(indices.size() - 1), context).getDataFlowInfo();
1321            }
1322    
1323            if (!isGet) {
1324                dataFlowInfo = facade.getTypeInfo(rightHandSide, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
1325            }
1326    
1327            if (!functionResults.isSingleResult()) {
1328                traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression));
1329                return JetTypeInfo.create(null, dataFlowInfo);
1330            }
1331            traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall());
1332            return JetTypeInfo.create(functionResults.getResultingDescriptor().getReturnType(), dataFlowInfo);
1333        }
1334    }