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