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.Multimap;
020    import com.intellij.lang.ASTNode;
021    import com.intellij.psi.PsiElement;
022    import com.intellij.psi.tree.IElementType;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.jet.JetNodeTypes;
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.ResolutionResultsCache;
040    import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode;
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.checker.TypeCheckingProcedure;
060    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
061    import org.jetbrains.jet.lexer.JetTokens;
062    import org.jetbrains.jet.utils.ThrowingList;
063    
064    import java.util.*;
065    
066    import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
067    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
068    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
069    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
070    import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
071    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
072    import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
073    
074    @SuppressWarnings("SuspiciousMethodCalls")
075    public 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    }