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.diagnostics.Diagnostic;
029    import org.jetbrains.jet.lang.diagnostics.Errors;
030    import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
031    import org.jetbrains.jet.lang.psi.*;
032    import org.jetbrains.jet.lang.resolve.*;
033    import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver;
034    import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver;
035    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
036    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
037    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
038    import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability;
039    import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
040    import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
041    import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
042    import org.jetbrains.jet.lang.resolve.calls.model.DataFlowInfoForArgumentsImpl;
043    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
044    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
045    import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
046    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
047    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
048    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
049    import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
050    import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
051    import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
052    import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
053    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
054    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantChecker;
055    import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant;
056    import org.jetbrains.jet.lang.resolve.name.LabelName;
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.INSTANCE;
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                JetLabelQualifiedInstanceExpression expression,
375                ExpressionTypingContext context,
376                boolean onlyClassReceivers
377        ) {
378            String labelName = expression.getLabelName();
379            if (labelName != null) {
380                LabelResolver.LabeledReceiverResolutionResult resolutionResult = context.labelResolver.resolveThisLabel(
381                        expression.getInstanceReference(), expression.getTargetLabel(), context, new LabelName(labelName));
382                if (onlyClassReceivers && resolutionResult.success()) {
383                    if (!isDeclaredInClass(resolutionResult.getReceiverParameterDescriptor())) {
384                        return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(NO_RECEIVER_PARAMETER);
385                    }
386                }
387                return resolutionResult;
388            }
389            else {
390                ReceiverParameterDescriptor result = NO_RECEIVER_PARAMETER;
391                List<ReceiverParameterDescriptor> receivers = context.scope.getImplicitReceiversHierarchy();
392                if (onlyClassReceivers) {
393                    for (ReceiverParameterDescriptor receiver : receivers) {
394                        if (isDeclaredInClass(receiver)) {
395                            result = receiver;
396                            break;
397                        }
398                    }
399                }
400                else if (!receivers.isEmpty()) {
401                    result = receivers.get(0);
402                }
403                if (result != NO_RECEIVER_PARAMETER) {
404                    context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration());
405                    recordThisOrSuperCallInTraceAndCallExtension(context, result, expression);
406    
407                }
408                return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result);
409            }
410        }
411    
412        private static void recordThisOrSuperCallInTraceAndCallExtension(
413                ExpressionTypingContext context,
414                ReceiverParameterDescriptor descriptor,
415                JetExpression expression
416        ) {
417            BindingTrace trace = context.trace;
418            Call call = CallMaker.makeCall(expression, NO_RECEIVER, null, expression, Collections.<ValueArgument>emptyList());
419            ResolutionCandidate<ReceiverParameterDescriptor> resolutionCandidate =
420                    ResolutionCandidate.create(
421                            call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false);
422    
423            ResolvedCallImpl<ReceiverParameterDescriptor> resolvedCall =
424                    ResolvedCallImpl.create(resolutionCandidate,
425                                            TemporaryBindingTrace.create(trace, "Fake trace for fake 'this' or 'super' resolved call"),
426                                            TracingStrategy.EMPTY,
427                                            new DataFlowInfoForArgumentsImpl(call));
428            resolvedCall.markCallAsCompleted();
429    
430            trace.record(RESOLVED_CALL, expression, resolvedCall);
431            trace.record(CALL, expression, call);
432    
433            context.callResolverExtension.run(resolvedCall,
434                                              BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.DISABLED));
435        }
436    
437        private static boolean isDeclaredInClass(ReceiverParameterDescriptor receiver) {
438            return receiver.getContainingDeclaration() instanceof ClassDescriptor;
439        }
440    
441        @Override
442        public JetTypeInfo visitBlockExpression(@NotNull JetBlockExpression expression, ExpressionTypingContext context) {
443            return components.expressionTypingServices.getBlockReturnedType(expression, context, false);
444        }
445    
446        @Override
447        public JetTypeInfo visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, ExpressionTypingContext context) {
448            JetTypeReference typeReference = expression.getTypeReference();
449    
450            JetType receiverType =
451                    typeReference == null
452                    ? null
453                    : components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, false);
454    
455            JetSimpleNameExpression callableReference = expression.getCallableReference();
456            if (callableReference.getReferencedName().isEmpty()) {
457                context.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference));
458                JetType errorType = ErrorUtils.createErrorType("Empty callable reference");
459                return DataFlowUtils.checkType(errorType, expression, context, context.dataFlowInfo);
460            }
461    
462            JetType result = getCallableReferenceType(expression, receiverType, context);
463            return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
464        }
465    
466        @Nullable
467        private JetType getCallableReferenceType(
468                @NotNull JetCallableReferenceExpression expression,
469                @Nullable JetType lhsType,
470                @NotNull ExpressionTypingContext context
471        ) {
472            JetSimpleNameExpression reference = expression.getCallableReference();
473    
474            boolean[] result = new boolean[1];
475            FunctionDescriptor descriptor = resolveCallableReferenceTarget(lhsType, context, expression, result);
476    
477            if (!result[0]) {
478                context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
479            }
480            if (descriptor == null) return null;
481    
482            ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
483            ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
484            if (receiverParameter != null && expectedThisObject != null) {
485                context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, descriptor));
486                return null;
487            }
488    
489            JetType receiverType = null;
490            if (receiverParameter != null) {
491                receiverType = receiverParameter.getType();
492            }
493            else if (expectedThisObject != null) {
494                receiverType = expectedThisObject.getType();
495            }
496    
497            //noinspection ConstantConditions
498            JetType type = components.reflectionTypes.getKFunctionType(
499                    Annotations.EMPTY,
500                    receiverType,
501                    DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()),
502                    descriptor.getReturnType(),
503                    receiverParameter != null
504            );
505    
506            AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
507                    context.scope.getContainingDeclaration(),
508                    Annotations.EMPTY,
509                    CallableMemberDescriptor.Kind.DECLARATION);
510    
511            FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
512    
513            context.trace.record(FUNCTION, expression, functionDescriptor);
514    
515            return type;
516        }
517    
518        @Nullable
519        private FunctionDescriptor resolveCallableReferenceTarget(
520                @Nullable JetType lhsType,
521                @NotNull ExpressionTypingContext context,
522                @NotNull JetCallableReferenceExpression expression,
523                @NotNull boolean[] result
524        ) {
525            JetSimpleNameExpression reference = expression.getCallableReference();
526    
527            if (lhsType == null) {
528                return resolveCallableNotCheckingArguments(reference, NO_RECEIVER, context, result);
529            }
530    
531            ClassifierDescriptor classifier = lhsType.getConstructor().getDeclarationDescriptor();
532            if (!(classifier instanceof ClassDescriptor)) {
533                context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(expression));
534                return null;
535            }
536    
537            ReceiverValue receiver = new TransientReceiver(lhsType);
538            TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
539                    context, "trace to resolve callable reference with receiver", reference);
540            FunctionDescriptor descriptor = resolveCallableNotCheckingArguments(
541                    reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
542            if (result[0]) {
543                temporaryWithReceiver.commit();
544                return descriptor;
545            }
546    
547            JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier);
548            TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
549                    context, "trace to resolve callable reference in static scope", reference);
550            FunctionDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
551                    context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
552            if (result[0]) {
553                temporaryForStatic.commit();
554                return possibleStaticNestedClassConstructor;
555            }
556    
557            return null;
558        }
559    
560        @Nullable
561        private FunctionDescriptor resolveCallableNotCheckingArguments(
562                @NotNull JetSimpleNameExpression reference,
563                @NotNull ReceiverValue receiver,
564                @NotNull ExpressionTypingContext context,
565                @NotNull boolean[] result
566        ) {
567            Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
568    
569            TemporaryBindingTrace trace = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", reference);
570    
571            ExpressionTypingContext contextForResolve = context.replaceBindingTrace(trace).replaceExpectedType(NO_EXPECTED_TYPE);
572            ResolvedCall<FunctionDescriptor> function = components.expressionTypingServices.getCallExpressionResolver()
573                    .getResolvedCallForFunction(call, reference, contextForResolve, CheckValueArgumentsMode.DISABLED, result);
574            if (!result[0]) return null;
575    
576            if (function instanceof VariableAsFunctionResolvedCall) {
577                // TODO: KProperty
578                context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
579                context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
580                return null;
581            }
582    
583            trace.commit();
584            return function != null ? function.getResultingDescriptor() : null;
585        }
586    
587        @Override
588        public JetTypeInfo visitQualifiedExpression(@NotNull JetQualifiedExpression expression, ExpressionTypingContext context) {
589            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
590            return callExpressionResolver.getQualifiedExpressionTypeInfo(expression, context);
591        }
592    
593        @Override
594        public JetTypeInfo visitCallExpression(@NotNull JetCallExpression expression, ExpressionTypingContext context) {
595            CallExpressionResolver callExpressionResolver = components.expressionTypingServices.getCallExpressionResolver();
596            return callExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context);
597        }
598    
599        @Override
600        public JetTypeInfo visitUnaryExpression(@NotNull JetUnaryExpression expression, ExpressionTypingContext context) {
601            return visitUnaryExpression(expression, context, false);
602        }
603    
604        public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
605            ExpressionTypingContext context = isUnaryExpressionDependentOnExpectedType(expression)
606                    ? contextWithExpectedType
607                    : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
608    
609            JetExpression baseExpression = expression.getBaseExpression();
610            if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
611    
612            JetSimpleNameExpression operationSign = expression.getOperationReference();
613    
614            IElementType operationType = operationSign.getReferencedNameElementType();
615            // If it's a labeled expression
616            if (JetTokens.LABELS.contains(operationType)) {
617                return visitLabeledExpression(expression, context, isStatement);
618            }
619    
620            // Special case for expr!!
621            if (operationType == JetTokens.EXCLEXCL) {
622                return visitExclExclExpression(expression, context);
623            }
624    
625            // Type check the base expression
626            JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context);
627            JetType type = typeInfo.getType();
628            if (type == null) {
629                return typeInfo;
630            }
631            DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
632    
633            // Conventions for unary operations
634            Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
635            if (name == null) {
636                context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
637                return JetTypeInfo.create(null, dataFlowInfo);
638            }
639    
640            // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
641            if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) {
642                JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
643                resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression,
644                                            stubExpression,
645                                            context.replaceBindingTrace(
646                                                    TemporaryBindingTrace.create(context.trace, "trace to resolve array access set method for unary expression", expression)),
647                                            context.trace);
648            }
649    
650            ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type);
651    
652            // Resolve the operation reference
653            OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(
654                    context,
655                    CallMaker.makeCall(receiver, expression),
656                    expression.getOperationReference(),
657                    name);
658    
659            if (!resolutionResults.isSuccess()) {
660                return JetTypeInfo.create(null, dataFlowInfo);
661            }
662    
663            // Computing the return type
664            JetType returnType = resolutionResults.getResultingDescriptor().getReturnType();
665            JetType result;
666            if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
667                assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
668                if (JetTypeChecker.INSTANCE.isSubtypeOf(returnType, KotlinBuiltIns.getInstance().getUnitType())) {
669                    result = ErrorUtils.createErrorType(KotlinBuiltIns.getInstance().getUnit().getName().asString());
670                    context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
671                }
672                else {
673                    JetType receiverType = receiver.getType();
674                    if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, receiverType)) {
675                        context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
676                    }
677                    else {
678                        context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
679    
680                        checkLValue(context.trace, baseExpression);
681                    }
682                    // TODO : Maybe returnType?
683                    result = receiverType;
684                }
685            }
686            else {
687                result = returnType;
688            }
689    
690            CompileTimeConstant<?> value = ConstantExpressionEvaluator.object$.evaluate(expression, contextWithExpectedType.trace,
691                                                                                        contextWithExpectedType.expectedType);
692            if (value != null) {
693                return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
694            }
695    
696            return DataFlowUtils.checkType(result, expression, contextWithExpectedType, dataFlowInfo);
697        }
698    
699        @NotNull
700        public static JetTypeInfo createCompileTimeConstantTypeInfo(
701                @NotNull CompileTimeConstant<?> value,
702                @NotNull JetExpression expression,
703                @NotNull ExpressionTypingContext context
704        ) {
705            JetType expressionType = value.getType(KotlinBuiltIns.getInstance());
706            if (value instanceof IntegerValueTypeConstant && context.contextDependency == INDEPENDENT) {
707                expressionType = ((IntegerValueTypeConstant) value).getType(context.expectedType);
708                ArgumentTypeResolver.updateNumberType(expressionType, expression, context.trace);
709            }
710    
711            return DataFlowUtils.checkType(expressionType, expression, context, context.dataFlowInfo);
712        }
713    
714        private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) {
715            JetExpression baseExpression = expression.getBaseExpression();
716            assert baseExpression != null;
717            JetSimpleNameExpression operationSign = expression.getOperationReference();
718            assert operationSign.getReferencedNameElementType() == JetTokens.EXCLEXCL;
719    
720            Call call = createCallForSpecialConstruction(expression, Collections.singletonList(baseExpression));
721            components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
722                    call, "ExclExcl", Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null);
723            JetTypeInfo baseTypeInfo = BindingContextUtils.getRecordedTypeInfo(baseExpression, context.trace.getBindingContext());
724            assert baseTypeInfo != null : "Base expression was not processed: " + expression;
725            JetType baseType = baseTypeInfo.getType();
726            if (baseType == null) {
727                return baseTypeInfo;
728            }
729            DataFlowInfo dataFlowInfo = baseTypeInfo.getDataFlowInfo();
730            if (isKnownToBeNotNull(baseExpression, context) && !baseType.isError()) {
731                context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, baseType));
732            }
733            else {
734                DataFlowValue value = DataFlowValueFactory.createDataFlowValue(baseExpression, baseType, context.trace.getBindingContext());
735                dataFlowInfo = dataFlowInfo.disequate(value, DataFlowValue.NULL);
736            }
737            return JetTypeInfo.create(TypeUtils.makeNotNullable(baseType), dataFlowInfo);
738        }
739    
740        private JetTypeInfo visitLabeledExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context,
741                boolean isStatement) {
742            JetExpression baseExpression = expression.getBaseExpression();
743            assert baseExpression != null;
744            JetSimpleNameExpression operationSign = expression.getOperationReference();
745            assert JetTokens.LABELS.contains(operationSign.getReferencedNameElementType());
746    
747            String referencedName = operationSign.getReferencedName();
748            context.labelResolver.enterLabeledElement(new LabelName(referencedName.substring(1)), baseExpression);
749            // TODO : Some processing for the label?
750            JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context, isStatement);
751            context.labelResolver.exitLabeledElement(baseExpression);
752            return typeInfo;
753        }
754    
755        private static boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) {
756            JetType type = context.trace.get(EXPRESSION_TYPE, expression);
757            assert type != null : "This method is only supposed to be called when the type is not null";
758            return isKnownToBeNotNull(expression, type, context);
759        }
760    
761        private static boolean isKnownToBeNotNull(JetExpression expression, JetType jetType, ExpressionTypingContext context) {
762            DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, jetType, context.trace.getBindingContext());
763            return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull();
764        }
765    
766        public static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) {
767            checkLValue(trace, expression, false);
768        }
769    
770        private static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expressionWithParenthesis, boolean canBeThis) {
771            JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
772            if (expression instanceof JetArrayAccessExpression) {
773                JetExpression arrayExpression = ((JetArrayAccessExpression) expression).getArrayExpression();
774                if (arrayExpression != null) {
775                    checkLValue(trace, arrayExpression, true);
776                }
777                return;
778            }
779            if (canBeThis && expression instanceof JetThisExpression) return;
780            VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
781    
782            JetExpression reportOn = expression != null ? expression : expressionWithParenthesis;
783            if (variable instanceof PropertyDescriptor) {
784                PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
785                if (propertyDescriptor.isSetterProjectedOut()) {
786                    trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
787                }
788            }
789    
790            if (variable == null) {
791                trace.report(VARIABLE_EXPECTED.on(reportOn));
792            }
793        }
794    
795        @Override
796        public JetTypeInfo visitBinaryExpression(@NotNull JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
797            ExpressionTypingContext context = isBinaryExpressionDependentOnExpectedType(expression)
798                    ? contextWithExpectedType
799                    : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
800    
801            JetSimpleNameExpression operationSign = expression.getOperationReference();
802            JetExpression left = expression.getLeft();
803            JetExpression right = expression.getRight();
804            IElementType operationType = operationSign.getReferencedNameElementType();
805    
806            JetTypeInfo result;
807    
808            //Expressions that can depend on expected type
809            if (operationType == JetTokens.IDENTIFIER) {
810                Name referencedName = operationSign.getReferencedNameAsName();
811                result = getTypeInfoForBinaryCall(referencedName, context, expression);
812            }
813            else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) {
814                Name referencedName = OperatorConventions.BINARY_OPERATION_NAMES.get(operationType);
815                result = getTypeInfoForBinaryCall(referencedName, context, expression);
816            }
817            else if (operationType == JetTokens.ELVIS) {
818                //base expression of elvis operator is checked for 'type mismatch', so the whole expression shouldn't be checked
819                return visitElvisExpression(expression, context);
820            }
821    
822            //Expressions that don't depend on expected type
823            else if (operationType == JetTokens.EQ) {
824                result = visitAssignment(expression, context);
825            }
826            else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
827                result = visitAssignmentOperation(expression, context);
828            }
829            else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
830                result = visitComparison(expression, context, operationSign);
831            }
832            else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
833                result = visitEquality(expression, context, operationSign, left, right);
834            }
835            else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
836                ensureNonemptyIntersectionOfOperandTypes(expression, context);
837                // TODO : Check comparison pointlessness
838                result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), context.dataFlowInfo);
839            }
840            else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
841                result = checkInExpression(expression, operationSign, left, right, context);
842            }
843            else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
844                result = visitBooleanOperationExpression(operationType, left, right, context);
845            }
846            else {
847                context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
848                result = JetTypeInfo.create(null, context.dataFlowInfo);
849            }
850            CompileTimeConstant<?> value = ConstantExpressionEvaluator.object$.
851                    evaluate(expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType);
852            if (value != null) {
853                return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
854            }
855            return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
856        }
857    
858        private JetTypeInfo visitEquality(
859                JetBinaryExpression expression,
860                ExpressionTypingContext context,
861                JetSimpleNameExpression operationSign,
862                final JetExpression left,
863                final JetExpression right
864        ) {
865            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
866            if (right == null || left == null) {
867                ExpressionTypingUtils.getTypeInfoOrNullType(right, context, facade);
868                ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
869                return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo);
870            }
871            ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context);
872    
873            JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
874    
875            dataFlowInfo = leftTypeInfo.getDataFlowInfo();
876            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
877    
878            JetTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithDataFlow);
879            dataFlowInfo = rightTypeInfo.getDataFlowInfo();
880    
881            TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create(
882                    context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
883            traceInterpretingRightAsNullableAny.record(EXPRESSION_TYPE, right, KotlinBuiltIns.getInstance().getNullableAnyType());
884    
885            Call call = CallMaker.makeCallWithExpressions(operationSign, receiver, null, operationSign, Collections.singletonList(right));
886            ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
887            OverloadResolutionResults<FunctionDescriptor> resolutionResults =
888                    components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorConventions.EQUALS);
889    
890            traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() {
891                @Override
892                public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
893                    // the type of the right expression isn't 'Any?' actually
894                    if (key == right && slice == EXPRESSION_TYPE) return false;
895    
896                    // a hack due to KT-678
897                    // without this line an autocast is reported on the receiver (if it was previously checked for not-null)
898                    // with not-null check the resolution result changes from 'fun Any?.equals' to 'equals' member
899                    if (key == left && slice == AUTOCAST) return false;
900    
901                    return true;
902                }
903            }, true);
904    
905            if (resolutionResults.isSuccess()) {
906                FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
907                if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(), context)) {
908                    ensureNonemptyIntersectionOfOperandTypes(expression, context);
909                }
910            }
911            else {
912                if (resolutionResults.isAmbiguity()) {
913                    context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls()));
914                }
915                else {
916                    context.trace.report(EQUALS_MISSING.on(operationSign));
917                }
918            }
919            return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo);
920        }
921    
922        @NotNull
923        private JetTypeInfo visitComparison(
924                @NotNull JetBinaryExpression expression,
925                @NotNull ExpressionTypingContext context,
926                @NotNull JetSimpleNameExpression operationSign
927        ) {
928            JetTypeInfo typeInfo = getTypeInfoForBinaryCall(OperatorConventions.COMPARE_TO, context, expression);
929            DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
930            JetType compareToReturnType = typeInfo.getType();
931            JetType type = null;
932            if (compareToReturnType != null && !compareToReturnType.isError()) {
933                TypeConstructor constructor = compareToReturnType.getConstructor();
934                KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
935                TypeConstructor intTypeConstructor = builtIns.getInt().getTypeConstructor();
936                if (constructor.equals(intTypeConstructor)) {
937                    type = builtIns.getBooleanType();
938                }
939                else {
940                    context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType));
941                }
942            }
943            return JetTypeInfo.create(type, dataFlowInfo);
944        }
945    
946        @NotNull
947        private JetTypeInfo visitBooleanOperationExpression(
948                @Nullable IElementType operationType,
949                @Nullable JetExpression left,
950                @Nullable JetExpression right,
951                @NotNull ExpressionTypingContext context
952        ) {
953            JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
954            JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context.replaceExpectedType(booleanType), facade);
955            DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
956    
957            WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||");
958            // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
959            boolean isAnd = operationType == JetTokens.ANDAND;
960            DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
961            WritableScopeImpl rightScope = isAnd ? leftScope : newWritableScopeImpl(context, "Right scope of && or ||");
962    
963            ExpressionTypingContext contextForRightExpr =
964                    context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope).replaceExpectedType(booleanType);
965            if (right != null) {
966                facade.getTypeInfo(right, contextForRightExpr);
967            }
968            return JetTypeInfo.create(booleanType, dataFlowInfo);
969        }
970    
971        @NotNull
972        private JetTypeInfo visitElvisExpression(
973                @NotNull JetBinaryExpression expression,
974                @NotNull ExpressionTypingContext contextWithExpectedType
975        ) {
976            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
977            JetExpression left = expression.getLeft();
978            JetExpression right = expression.getRight();
979    
980            if (left == null || right == null) {
981                getTypeInfoOrNullType(left, context, facade);
982                return JetTypeInfo.create(null, context.dataFlowInfo);
983            }
984    
985            Call call = createCallForSpecialConstruction(expression, Lists.newArrayList(left, right));
986            ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
987                    call, "Elvis", Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
988            JetTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
989            assert leftTypeInfo != null : "Left expression was not processed: " + expression;
990            JetType leftType = leftTypeInfo.getType();
991            if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
992                context.trace.report(USELESS_ELVIS.on(left, leftType));
993            }
994            JetTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext());
995            assert rightTypeInfo != null : "Right expression was not processed: " + expression;
996            JetType rightType = rightTypeInfo.getType();
997    
998            DataFlowInfo dataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
999            JetType type = resolvedCall.getResultingDescriptor().getReturnType();
1000            if (type == null || rightType == null) return JetTypeInfo.create(null, dataFlowInfo);
1001    
1002            return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified(type, rightType.isNullable()), dataFlowInfo);
1003        }
1004    
1005        @NotNull
1006        public JetTypeInfo checkInExpression(
1007                @NotNull JetElement callElement,
1008                @NotNull JetSimpleNameExpression operationSign,
1009                @Nullable JetExpression left,
1010                @Nullable JetExpression right,
1011                @NotNull ExpressionTypingContext context
1012        ) {
1013            ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
1014            if (right == null) {
1015                if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
1016                return JetTypeInfo.create(null, context.dataFlowInfo);
1017            }
1018    
1019            DataFlowInfo dataFlowInfo = facade.getTypeInfo(right, contextWithNoExpectedType).getDataFlowInfo();
1020    
1021            ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, contextWithNoExpectedType);
1022            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1023    
1024            OverloadResolutionResults<FunctionDescriptor> resolutionResult = components.callResolver.resolveCallWithGivenName(
1025                    contextWithDataFlow,
1026                    CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)),
1027                    operationSign,
1028                    OperatorConventions.CONTAINS);
1029            JetType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
1030            ensureBooleanResult(operationSign, OperatorConventions.CONTAINS, containsType, context);
1031    
1032            if (left != null) {
1033                dataFlowInfo = facade.getTypeInfo(left, contextWithDataFlow).getDataFlowInfo().and(dataFlowInfo);
1034            }
1035    
1036            return JetTypeInfo.create(resolutionResult.isSuccess() ? KotlinBuiltIns.getInstance().getBooleanType() : null, dataFlowInfo);
1037        }
1038    
1039        private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
1040            JetExpression left = expression.getLeft();
1041            if (left == null) return;
1042    
1043            JetExpression right = expression.getRight();
1044    
1045            // TODO : duplicated effort for == and !=
1046            JetType leftType = facade.getTypeInfo(left, context).getType();
1047            if (leftType != null && right != null) {
1048                JetType rightType = facade.getTypeInfo(right, context).getType();
1049    
1050                if (rightType != null) {
1051                    if (TypeUtils.isIntersectionEmpty(leftType, rightType)) {
1052                        context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType));
1053                    }
1054                    checkSenselessComparisonWithNull(expression, left, right, context);
1055                }
1056            }
1057        }
1058    
1059        private void checkSenselessComparisonWithNull(@NotNull JetBinaryExpression expression, @NotNull JetExpression left, @NotNull JetExpression right, @NotNull ExpressionTypingContext context) {
1060            JetExpression expr;
1061            if (JetPsiUtil.isNullConstant(left)) {
1062                expr = right;
1063            }
1064            else if (JetPsiUtil.isNullConstant(right)) {
1065                expr = left;
1066            }
1067            else return;
1068    
1069            JetSimpleNameExpression operationSign = expression.getOperationReference();
1070            JetType type = facade.getTypeInfo(expr, context).getType();
1071            if (type == null || type.isError()) return;
1072    
1073            DataFlowValue value = DataFlowValueFactory.createDataFlowValue(expr, type, context.trace.getBindingContext());
1074            Nullability nullability = context.dataFlowInfo.getNullability(value);
1075    
1076            boolean expressionIsAlways;
1077            boolean equality = operationSign.getReferencedNameElementType() == JetTokens.EQEQ || operationSign.getReferencedNameElementType() == JetTokens.EQEQEQ;
1078    
1079            if (nullability == Nullability.NULL) {
1080                expressionIsAlways = equality;
1081            }
1082            else if (nullability == Nullability.NOT_NULL) {
1083                expressionIsAlways = !equality;
1084            }
1085            else return;
1086    
1087            context.trace.report(SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways));
1088        }
1089    
1090        @NotNull
1091        private JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
1092            return assignmentIsNotAnExpressionError(expression, context);
1093        }
1094    
1095        @NotNull
1096        private JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
1097            return assignmentIsNotAnExpressionError(expression, context);
1098        }
1099    
1100        @NotNull
1101        private JetTypeInfo assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) {
1102            facade.checkStatementType(expression, context);
1103            context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression));
1104            return JetTypeInfo.create(null, context.dataFlowInfo);
1105        }
1106    
1107        @Override
1108        public JetTypeInfo visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, ExpressionTypingContext context) {
1109            JetTypeInfo typeInfo = resolveArrayAccessGetMethod(expression, context);
1110            return DataFlowUtils.checkType(typeInfo, expression, context);
1111        }
1112    
1113        @NotNull
1114        public JetTypeInfo getTypeInfoForBinaryCall(
1115                @NotNull Name name,
1116                @NotNull ExpressionTypingContext context,
1117                @NotNull JetBinaryExpression binaryExpression
1118        ) {
1119            JetExpression left = binaryExpression.getLeft();
1120            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
1121            if (left != null) {
1122                //left here is a receiver, so it doesn't depend on expected type
1123                dataFlowInfo = facade.getTypeInfo(
1124                        left, context.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
1125            }
1126            ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
1127    
1128            OverloadResolutionResults<FunctionDescriptor> resolutionResults;
1129            if (left != null) {
1130                ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
1131                resolutionResults = components.callResolver.resolveBinaryCall(
1132                        contextWithDataFlow.replaceScope(context.scope),
1133                        receiver, binaryExpression, name
1134                );
1135            }
1136            else {
1137                resolutionResults = OverloadResolutionResultsImpl.nameNotFound();
1138            }
1139    
1140            if (resolutionResults.isSingleResult()) {
1141                dataFlowInfo = resolutionResults.getResultingCall().getDataFlowInfoForArguments().getResultInfo();
1142            }
1143    
1144            return JetTypeInfo.create(OverloadResolutionResultsUtil.getResultingType(resolutionResults, context.contextDependency), dataFlowInfo);
1145        }
1146    
1147        @Override
1148        public JetTypeInfo visitDeclaration(@NotNull JetDeclaration dcl, ExpressionTypingContext context) {
1149            context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl));
1150            return JetTypeInfo.create(null, context.dataFlowInfo);
1151        }
1152    
1153        @Override
1154        public JetTypeInfo visitRootPackageExpression(@NotNull JetRootPackageExpression expression, ExpressionTypingContext context) {
1155            if (JetPsiUtil.isLHSOfDot(expression)) {
1156                return DataFlowUtils.checkType(JetModuleUtil.getRootPackageType(expression), expression, context, context.dataFlowInfo);
1157            }
1158            context.trace.report(PACKAGE_IS_NOT_AN_EXPRESSION.on(expression));
1159            return JetTypeInfo.create(null, context.dataFlowInfo);
1160        }
1161    
1162    
1163        @Override
1164        public JetTypeInfo visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) {
1165            final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
1166            final DataFlowInfo[] dataFlowInfo = new DataFlowInfo[] { context.dataFlowInfo };
1167            for (JetStringTemplateEntry entry : expression.getEntries()) {
1168                entry.accept(new JetVisitorVoid() {
1169    
1170                    @Override
1171                    public void visitStringTemplateEntryWithExpression(@NotNull JetStringTemplateEntryWithExpression entry) {
1172                        JetExpression entryExpression = entry.getExpression();
1173                        if (entryExpression != null) {
1174                            JetTypeInfo typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(dataFlowInfo[0]));
1175                            dataFlowInfo[0] = typeInfo.getDataFlowInfo();
1176                        }
1177                    }
1178    
1179                    @Override
1180                    public void visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry) {
1181                        CompileTimeConstantChecker.CharacterWithDiagnostic value = CompileTimeConstantChecker.escapedStringToCharacter(entry.getText(), entry);
1182                        Diagnostic diagnostic = value.getDiagnostic();
1183                        if (diagnostic != null) {
1184                            context.trace.report(diagnostic);
1185                        }
1186                    }
1187                });
1188            }
1189            ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, contextWithExpectedType.expectedType);
1190            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getStringType(), expression, contextWithExpectedType, dataFlowInfo[0]);
1191        }
1192    
1193        @Override
1194        public JetTypeInfo visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression, ExpressionTypingContext context) {
1195            return visitAnnotatedExpression(expression, context, false);
1196        }
1197    
1198        public JetTypeInfo visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
1199            components.expressionTypingServices.getAnnotationResolver().resolveAnnotationsWithArguments(
1200                    context.scope, expression.getAnnotationEntries(), context.trace);
1201    
1202            JetExpression baseExpression = expression.getBaseExpression();
1203            if (baseExpression == null) {
1204                return JetTypeInfo.create(null, context.dataFlowInfo);
1205            }
1206            return facade.getTypeInfo(baseExpression, context, isStatement);
1207        }
1208    
1209        @Override
1210        public JetTypeInfo visitJetElement(@NotNull JetElement element, ExpressionTypingContext context) {
1211            context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
1212            return JetTypeInfo.create(null, context.dataFlowInfo);
1213        }
1214    
1215        @NotNull
1216            /*package*/ JetTypeInfo resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) {
1217            return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
1218        }
1219    
1220        @NotNull
1221            /*package*/ JetTypeInfo resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) {
1222            return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
1223        }
1224    
1225        @NotNull
1226        private JetTypeInfo resolveArrayAccessSpecialMethod(@NotNull JetArrayAccessExpression arrayAccessExpression,
1227                                                        @Nullable JetExpression rightHandSide, //only for 'set' method
1228                                                        @NotNull ExpressionTypingContext oldContext,
1229                                                        @NotNull BindingTrace traceForResolveResult,
1230                                                        boolean isGet) {
1231            JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
1232            if (arrayExpression == null) return JetTypeInfo.create(null, oldContext.dataFlowInfo);
1233    
1234            JetTypeInfo arrayTypeInfo = facade.getTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
1235                    .replaceContextDependency(INDEPENDENT));
1236            JetType arrayType = arrayTypeInfo.getType();
1237            if (arrayType == null) {
1238                for (JetExpression indexExpression : arrayAccessExpression.getIndexExpressions()) {
1239                    facade.getTypeInfo(indexExpression, oldContext);
1240                }
1241                return arrayTypeInfo;
1242            }
1243    
1244            DataFlowInfo dataFlowInfo = arrayTypeInfo.getDataFlowInfo();
1245            ExpressionTypingContext context = oldContext.replaceDataFlowInfo(dataFlowInfo);
1246            ExpressionReceiver receiver = new ExpressionReceiver(arrayExpression, arrayType);
1247            if (!isGet) assert rightHandSide != null;
1248    
1249            OverloadResolutionResults<FunctionDescriptor> functionResults = components.callResolver.resolveCallWithGivenName(
1250                    context,
1251                    isGet
1252                    ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD)
1253                    : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD),
1254                    arrayAccessExpression,
1255                    Name.identifier(isGet ? "get" : "set")
1256            );
1257    
1258            List<JetExpression> indices = arrayAccessExpression.getIndexExpressions();
1259            // The accumulated data flow info of all index expressions is saved on the last index
1260            if (!indices.isEmpty()) {
1261                dataFlowInfo = facade.getTypeInfo(indices.get(indices.size() - 1), context).getDataFlowInfo();
1262            }
1263    
1264            if (!isGet) {
1265                dataFlowInfo = facade.getTypeInfo(rightHandSide, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
1266            }
1267    
1268            if (!functionResults.isSingleResult()) {
1269                traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression));
1270                return JetTypeInfo.create(null, dataFlowInfo);
1271            }
1272            traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall());
1273            return JetTypeInfo.create(functionResults.getResultingDescriptor().getReturnType(), dataFlowInfo);
1274        }
1275    }