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