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