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