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