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