JetTypeInferrer.java 108.5 KB
Newer Older
1 2
package org.jetbrains.jet.lang.types;

D
Dmitry Jemerov 已提交
3
import com.google.common.collect.ImmutableMap;
4
import com.google.common.collect.Lists;
5
import com.google.common.collect.Maps;
6
import com.google.common.collect.Sets;
7
import com.intellij.lang.ASTNode;
8
import com.intellij.psi.PsiElement;
9 10 11 12 13
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.JetSemanticServices;
14
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
A
Andrey Breslav 已提交
15
import org.jetbrains.jet.lang.descriptors.*;
16 17 18
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lexer.JetTokens;
19
import org.jetbrains.jet.resolve.DescriptorRenderer;
20 21 22 23 24 25 26 27

import java.util.*;

/**
 * @author abreslav
 */
public class JetTypeInferrer {

D
Dmitry Jemerov 已提交
28 29 30 31 32 33 34
    private static final Map<IElementType, String> unaryOperationNames = ImmutableMap.<IElementType, String>builder()
            .put(JetTokens.PLUSPLUS, "inc")
            .put(JetTokens.MINUSMINUS, "dec")
            .put(JetTokens.PLUS, "plus")
            .put(JetTokens.MINUS, "minus")
            .put(JetTokens.EXCL, "not")
            .build();
A
Andrey Breslav 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

    private static final Map<IElementType, String> binaryOperationNames = new HashMap<IElementType, String>();
    static {
        binaryOperationNames.put(JetTokens.MUL, "times");
        binaryOperationNames.put(JetTokens.PLUS, "plus");
        binaryOperationNames.put(JetTokens.MINUS, "minus");
        binaryOperationNames.put(JetTokens.DIV, "div");
        binaryOperationNames.put(JetTokens.PERC, "mod");
        binaryOperationNames.put(JetTokens.ARROW, "arrow");
        binaryOperationNames.put(JetTokens.RANGE, "rangeTo");
    }

    private static final Set<IElementType> comparisonOperations = new HashSet<IElementType>(Arrays.asList(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ));
    private static final Set<IElementType> equalsOperations = new HashSet<IElementType>(Arrays.asList(JetTokens.EQEQ, JetTokens.EXCLEQ));
    private static final Set<IElementType> inOperations = new HashSet<IElementType>(Arrays.asList(JetTokens.IN_KEYWORD, JetTokens.NOT_IN));

A
Andrey Breslav 已提交
51
    public static final Map<IElementType, String> assignmentOperationNames = new HashMap<IElementType, String>();
A
Andrey Breslav 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
    static {
        assignmentOperationNames.put(JetTokens.MULTEQ, "timesAssign");
        assignmentOperationNames.put(JetTokens.DIVEQ, "divAssign");
        assignmentOperationNames.put(JetTokens.PERCEQ, "modAssign");
        assignmentOperationNames.put(JetTokens.PLUSEQ, "plusAssign");
        assignmentOperationNames.put(JetTokens.MINUSEQ, "minusAssign");
    }

    private static final Map<IElementType, IElementType> assignmentOperationCounterparts = new HashMap<IElementType, IElementType>();
    static {
        assignmentOperationCounterparts.put(JetTokens.MULTEQ, JetTokens.MUL);
        assignmentOperationCounterparts.put(JetTokens.DIVEQ, JetTokens.DIV);
        assignmentOperationCounterparts.put(JetTokens.PERCEQ, JetTokens.PERC);
        assignmentOperationCounterparts.put(JetTokens.PLUSEQ, JetTokens.PLUS);
        assignmentOperationCounterparts.put(JetTokens.MINUSEQ, JetTokens.MINUS);
    }

69 70
    private final BindingTrace trace;
    private final JetSemanticServices semanticServices;
A
Andrey Breslav 已提交
71 72
    private final TypeResolver typeResolver;
    private final ClassDescriptorResolver classDescriptorResolver;
73
    private final JetFlowInformationProvider flowInformationProvider;
74

75
    public JetTypeInferrer(@NotNull BindingTrace trace, @NotNull JetFlowInformationProvider flowInformationProvider, @NotNull JetSemanticServices semanticServices) {
76
        this.trace = trace; //new CachedBindingTrace(trace);
77
        this.semanticServices = semanticServices;
78
        this.typeResolver = new TypeResolver(semanticServices, trace, true);
79
        this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
80
        this.flowInformationProvider = flowInformationProvider;
81 82
    }

83
    @NotNull
A
Andrey Breslav 已提交
84 85
    public JetType safeGetType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
        JetType type = getType(scope, expression, preferBlock);
86 87 88
        if (type != null) {
            return type;
        }
A
rename  
Andrey Breslav 已提交
89
        return ErrorUtils.createErrorType("Type for " + expression.getText());
90
    }
91

92
    @Nullable
A
Andrey Breslav 已提交
93
    public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
94
        return new TypeInferrerVisitor(scope, preferBlock, DataFlowInfo.getEmpty()).getType(expression);
95 96
    }

97
    public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
98
        return new TypeInferrerVisitorWithNamespaces(scope, preferBlock, DataFlowInfo.getEmpty()).getType(expression);
99 100
    }

101 102 103 104 105 106 107 108 109
    @Nullable
    private FunctionDescriptor lookupFunction(
            @NotNull JetScope scope,
            @NotNull JetReferenceExpression reference,
            @NotNull String name,
            @NotNull JetType receiverType,
            @NotNull List<JetType> argumentTypes,
            boolean reportUnresolved) {
        OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name);
110
        // No generics. Guaranteed
111
        overloadDomain = wrapForTracing(overloadDomain, reference, null, reportUnresolved);
112 113
        OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<JetType>emptyList(), argumentTypes);
        return resolutionResult.isSuccess() ? resolutionResult.getFunctionDescriptor() : null;
114 115
    }

116 117 118 119 120 121 122
    @NotNull
    private OverloadResolutionResult resolveNoParametersFunction(@NotNull JetType receiverType, @NotNull JetScope scope, @NotNull String name) {
        OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name);
        // No generics. Guaranteed
        return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<JetType>emptyList(), Collections.<JetType>emptyList());
    }

123
    private OverloadDomain getOverloadDomain(
124
            @Nullable final JetType receiverType,
125 126 127 128
            @NotNull final JetScope scope,
            @NotNull JetExpression calleeExpression,
            @Nullable PsiElement argumentList
    ) {
129
        final OverloadDomain[] result = new OverloadDomain[1];
130
        final JetSimpleNameExpression[] reference = new JetSimpleNameExpression[1];
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
        calleeExpression.accept(new JetVisitor() {

            @Override
            public void visitHashQualifiedExpression(JetHashQualifiedExpression expression) {
                // a#b -- create a domain for all overloads of b in a
                throw new UnsupportedOperationException(); // TODO
            }

            @Override
            public void visitPredicateExpression(JetPredicateExpression expression) {
                // overload lookup for checking, but the type is receiver's type + nullable
                throw new UnsupportedOperationException(); // TODO
            }

            @Override
            public void visitQualifiedExpression(JetQualifiedExpression expression) {
147 148
                trace.getErrorHandler().genericError(expression.getNode(), "Unsupported [JetTypeInferrer]");

149
                // . or ?.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
//                JetType receiverType = getType(scope, expression.getReceiverExpression(), false);
//                checkNullSafety(receiverType, expression.getOperationTokenNode());
//
//                JetExpression selectorExpression = expression.getSelectorExpression();
//                if (selectorExpression instanceof JetSimpleNameExpression) {
//                    JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression;
//                    String referencedName = referenceExpression.getReferencedName();
//
//                    if (receiverType != null && referencedName != null) {
//                        // No generics. Guaranteed
//                        result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
//                        reference[0] = referenceExpression;
//                    }
//                } else {
//                    throw new UnsupportedOperationException(); // TODO
//                }
166 167 168
            }

            @Override
169
            public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
170
                // a -- create a hierarchical lookup domain for this.a
171 172
                String referencedName = expression.getReferencedName();
                if (referencedName != null) {
173
                    // No generics. Guaranteed
174
                    result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
175 176
                    reference[0] = expression;
                }
177 178 179 180 181
            }

            @Override
            public void visitExpression(JetExpression expression) {
                // <e> create a dummy domain for the type of e
182
                throw new UnsupportedOperationException(expression.getText()); // TODO
183 184 185
            }

            @Override
186 187
            public void visitJetElement(JetElement element) {
                trace.getErrorHandler().genericError(element.getNode(), "Unsupported in call element"); // TODO : Message
188 189
            }
        });
190
        return wrapForTracing(result[0], reference[0], argumentList, true);
191 192
    }

193 194
    private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee) {
        if (receiverType != null && callee != null) {
195
            boolean namespaceType = receiverType instanceof NamespaceType;
196 197 198 199
            JetType calleeReceiverType = callee.getReceiverType();
            boolean nullableReceiver = !namespaceType && receiverType.isNullable();
            boolean calleeForbidsNullableReceiver = calleeReceiverType == null || !calleeReceiverType.isNullable();

200
            IElementType operationSign = operationTokenNode.getElementType();
201
            if (nullableReceiver && calleeForbidsNullableReceiver && operationSign == JetTokens.DOT) {
202
                trace.getErrorHandler().genericError(operationTokenNode, "Only safe calls (?.) are allowed on a nullable receiver of type " + receiverType);
A
Andrey Breslav 已提交
203
            }
204
            else if ((!nullableReceiver || !calleeForbidsNullableReceiver) && operationSign == JetTokens.SAFE_ACCESS) {
205
                if (namespaceType) {
206
                    trace.getErrorHandler().genericError(operationTokenNode, "Safe calls are not allowed on namespaces");
207 208
                }
                else {
209
                    trace.getErrorHandler().genericWarning(operationTokenNode, "Unnecessary safe call on a non-null receiver of type  " + receiverType);
210
                }
A
Andrey Breslav 已提交
211 212 213 214
            }
        }
    }

215
    private OverloadDomain wrapForTracing(
216 217
            @NotNull final OverloadDomain overloadDomain,
            @NotNull final JetReferenceExpression referenceExpression,
218
            @Nullable final PsiElement argumentList,
219
            final boolean reportErrors) {
220
        return new OverloadDomain() {
221
            @NotNull
222
            @Override
223 224 225 226
            public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
                OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType);
                report(resolutionResult);
                return resolutionResult;
227 228
            }

229
            @NotNull
230
            @Override
231 232 233 234 235 236 237 238 239 240 241 242 243
            public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
                OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes);
                report(resolutionResult);
                return resolutionResult;
            }

            private void report(OverloadResolutionResult resolutionResult) {
                if (resolutionResult.isSuccess() || resolutionResult.singleFunction()) {
                    trace.recordReferenceResolution(referenceExpression, resolutionResult.getFunctionDescriptor());
                }
                if (reportErrors) {
                    switch (resolutionResult.getResultCode()) {
                        case NAME_NOT_FOUND:
244
                            trace.getErrorHandler().unresolvedReference(referenceExpression);
245 246 247 248
                            break;
                        case SINGLE_FUNCTION_ARGUMENT_MISMATCH:
                            if (argumentList != null) {
                                // TODO : More helpful message. NOTE: there's a separate handling for this for constructors
249
                                trace.getErrorHandler().genericError(argumentList.getNode(), "Arguments do not match " + DescriptorRenderer.TEXT.render(resolutionResult.getFunctionDescriptor()));
250 251
                            }
                            else {
252
                                trace.getErrorHandler().unresolvedReference(referenceExpression);
253 254 255 256 257
                            }
                            break;
                        case AMBIGUITY:
                            if (argumentList != null) {
                                // TODO : More helpful message. NOTE: there's a separate handling for this for constructors
258
                                trace.getErrorHandler().genericError(argumentList.getNode(), "Overload ambiguity [TODO : more helpful message]");
259 260
                            }
                            else {
261
                                trace.getErrorHandler().unresolvedReference(referenceExpression);
262 263 264 265
                            }
                            break;
                        default:
                            // Not a success
266
                    }
A
Andrey Breslav 已提交
267
                }
268 269 270 271 272
            }

            @Override
            public boolean isEmpty() {
                return overloadDomain.isEmpty();
273 274 275 276
            }
        };
    }

277
    @NotNull
278
    public JetType getFunctionReturnType(@NotNull JetScope outerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
279
        Map<JetElement, JetType> typeMap = collectReturnedExpressions(outerScope, function, functionDescriptor);
280 281 282 283
        Collection<JetType> types = typeMap.values();
        return types.isEmpty() ? JetStandardClasses.getNothingType() : semanticServices.getTypeChecker().commonSupertype(types);
    }

284 285 286 287
//    private JetType getCachedType(@NotNull JetExpression expression) {
////        assert typeCache.containsKey(expression) : "No type cached for " + expression.getText();
//        return typeCache.get(expression);
//    }
288

289
    public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) {
290
        Map<JetElement, JetType> typeMap = collectReturnedExpressions(outerScope, function, functionDescriptor);
291 292 293 294 295 296 297
        if (typeMap.isEmpty()) {
            return; // The function returns Nothing
        }
        JetType expectedReturnType = functionDescriptor.getUnsubstitutedReturnType();
        for (Map.Entry<JetElement, JetType> entry : typeMap.entrySet()) {
            JetType actualType = entry.getValue();
            JetElement element = entry.getKey();
298 299 300
            JetTypeChecker typeChecker = semanticServices.getTypeChecker();
            if (!typeChecker.isSubtypeOf(actualType, expectedReturnType)) {
                if (typeChecker.isConvertibleBySpecialConversion(actualType, expectedReturnType)) {
301 302
                    if (expectedReturnType.getConstructor().equals(JetStandardClasses.getUnitType().getConstructor())
                        && element.getParent() instanceof JetReturnExpression) {
303
                        trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type Unit");
304
                    }
305 306
                }
                else {
A
Andrey Breslav 已提交
307 308 309
                    if (element == function) {
                        JetExpression bodyExpression = function.getBodyExpression();
                        assert bodyExpression != null;
310
                        trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType);
A
Andrey Breslav 已提交
311 312
                    }
                    else if (element instanceof JetExpression) {
313
                        JetExpression expression = (JetExpression) element;
314
                        trace.getErrorHandler().typeMismatch(expression, expectedReturnType, actualType);
315 316
                    }
                    else {
317
                        trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type " + expectedReturnType);
318
                    }
319 320 321 322 323
                }
            }
        }
    }

324
    private Map<JetElement, JetType> collectReturnedExpressions(JetScope outerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
325 326
        JetExpression bodyExpression = function.getBodyExpression();
        assert bodyExpression != null;
327
        JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
328 329 330
        getType(functionInnerScope, bodyExpression, function.hasBlockBody());
        Collection<JetExpression> returnedExpressions = new ArrayList<JetExpression>();
        Collection<JetElement> elementsReturningUnit = new ArrayList<JetElement>();
331
        flowInformationProvider.collectReturnedInformation(function.asElement(), returnedExpressions, elementsReturningUnit);
332 333
        Map<JetElement,JetType> typeMap = new HashMap<JetElement, JetType>();
        for (JetExpression returnedExpression : returnedExpressions) {
334
            JetType cachedType = trace.getBindingContext().getExpressionType(returnedExpression);// getCachedType(returnedExpression);
335
            trace.removeStatementRecord(returnedExpression);
336 337 338 339 340 341 342 343 344 345
            if (cachedType != null) {
                typeMap.put(returnedExpression, cachedType);
            }
        }
        for (JetElement jetElement : elementsReturningUnit) {
            typeMap.put(jetElement, JetStandardClasses.getUnitType());
        }
        return typeMap;
    }

346
    @Nullable
347
    private JetType getBlockReturnedType(@NotNull JetScope outerScope, @NotNull List<JetElement> block, DataFlowInfo dataFlowInfo) {
348 349
        if (block.isEmpty()) {
            return JetStandardClasses.getUnitType();
A
Andrey Breslav 已提交
350
        }
A
Andrey Breslav 已提交
351 352

        DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration();
A
Cleanup  
Andrey Breslav 已提交
353
        WritableScope scope = new WritableScopeImpl(outerScope, containingDescriptor, trace.getErrorHandler());
354
        return getBlockReturnedTypeWithWritableScope(scope, block, dataFlowInfo);
A
Andrey Breslav 已提交
355 356
    }

357
    private JetType getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List<? extends JetElement> block, DataFlowInfo dataFlowInfo) {
358 359 360
        if (block.isEmpty()) {
            return JetStandardClasses.getUnitType();
        }
A
Andrey Breslav 已提交
361

362
        TypeInferrerVisitorWithWritableScope blockLevelVisitor = new TypeInferrerVisitorWithWritableScope(scope, true, dataFlowInfo);
A
Andrey Breslav 已提交
363

A
Andrey Breslav 已提交
364 365
        JetType result = null;
        for (JetElement statement : block) {
366 367 368
            trace.recordStatement(statement);
            JetExpression statementExpression = (JetExpression) statement;
            result = blockLevelVisitor.getType(statementExpression);
369 370 371 372 373 374 375
            DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo();
            if (newDataFlowInfo != null) {
                blockLevelVisitor = new TypeInferrerVisitorWithWritableScope(scope, true, newDataFlowInfo);
            }
            else {
                blockLevelVisitor.resetResult(); // TODO : maybe it's better to recreate the visitors with the same scope?
            }
376
        }
A
Andrey Breslav 已提交
377
        return result;
378 379
    }

A
Andrey Breslav 已提交
380
    private void collectAllReturnTypes(JetWhenExpression whenExpression, JetScope scope, List<JetType> result) {
381 382 383 384 385 386 387
        for (JetWhenEntry entry : whenExpression.getEntries()) {
            JetWhenExpression subWhen = entry.getSubWhen();
            if (subWhen != null) {
                collectAllReturnTypes(subWhen, scope, result);
            } else {
                JetExpression resultExpression = entry.getExpression();
                if (resultExpression != null) {
388 389 390 391
                    JetType type = getType(scope, resultExpression, true);
                    if (type != null) {
                        result.add(type);
                    }
392 393 394 395 396
                }
            }
        }
    }

397
    @Nullable
A
Andrey Breslav 已提交
398
    private JetType resolveCall(
399 400
            @NotNull JetScope scope,
            @NotNull OverloadDomain overloadDomain,
A
Andrey Breslav 已提交
401
            @NotNull JetCall call) {
402 403 404
        // 1) ends with a name -> (scope, name) to look up
        // 2) ends with something else -> just check types

405
        final List<JetTypeProjection> jetTypeArguments = call.getTypeArguments();
A
Andrey Breslav 已提交
406

407
        for (JetTypeProjection typeArgument : jetTypeArguments) {
408
            if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
409
                trace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
410 411 412
            }
        }

A
Andrey Breslav 已提交
413 414
        final List<JetArgument> valueArguments = call.getValueArguments();

415 416 417 418 419 420 421 422
        boolean someNamed = false;
        for (JetArgument argument : valueArguments) {
            if (argument.isNamed()) {
                someNamed = true;
                break;
            }
        }

A
Andrey Breslav 已提交
423 424
        final List<JetExpression> functionLiteralArguments = call.getFunctionLiteralArguments();

425 426 427 428 429 430 431 432 433
        // TODO : must be a check
        assert functionLiteralArguments.size() <= 1;

        if (someNamed) {
            // TODO : check that all are named
            throw new UnsupportedOperationException(); // TODO

//                    result = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArguments, functionLiteralArgument);
        } else {
434 435
            List<JetType> typeArguments = new ArrayList<JetType>();
            for (JetTypeProjection projection : jetTypeArguments) {
436 437 438
                // TODO : check that there's no projection
                JetTypeReference typeReference = projection.getTypeReference();
                if (typeReference != null) {
439
                    typeArguments.add(typeResolver.resolveType(scope, typeReference));
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
                }
            }

            List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
            for (JetArgument argument : valueArguments) {
                JetExpression argumentExpression = argument.getArgumentExpression();
                if (argumentExpression != null) {
                    positionedValueArguments.add(argumentExpression);
                }
            }

            positionedValueArguments.addAll(functionLiteralArguments);

            List<JetType> valueArgumentTypes = new ArrayList<JetType>();
            for (JetExpression valueArgument : positionedValueArguments) {
                valueArgumentTypes.add(safeGetType(scope, valueArgument, false));
            }

458
            OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, valueArgumentTypes);
459
            if (resolutionResult.isSuccess()) {
460 461
                final FunctionDescriptor functionDescriptor = resolutionResult.getFunctionDescriptor();

462
                checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, functionDescriptor);
463
                return functionDescriptor.getUnsubstitutedReturnType();
464 465 466 467 468
            }
        }
        return null;
    }

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
    private void checkGenericBoundsInAFunctionCall(List<JetTypeProjection> jetTypeArguments, List<JetType> typeArguments, FunctionDescriptor functionDescriptor) {
        Map<TypeConstructor, TypeProjection> context = Maps.newHashMap();

        List<TypeParameterDescriptor> typeParameters = functionDescriptor.getOriginal().getTypeParameters();
        for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
            TypeParameterDescriptor typeParameter = typeParameters.get(i);
            JetType typeArgument = typeArguments.get(i);
            context.put(typeParameter.getTypeConstructor(), new TypeProjection(typeArgument));
        }
        TypeSubstitutor substitutor = TypeSubstitutor.create(context);
        for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
            TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
            JetType typeArgument = typeArguments.get(i);
            JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference();
            assert typeReference != null;
            classDescriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor);
        }
    }

488
    @Nullable
489
    public JetType checkConstructorCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) {
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
        JetTypeElement typeElement = typeReference.getTypeElement();
        if (typeElement instanceof JetUserType) {
            JetUserType userType = (JetUserType) typeElement;
            // TODO : to infer constructor parameters, one will need to
            //  1) resolve a _class_ from the typeReference
            //  2) rely on the overload domain of constructors of this class to infer type arguments
            // For now we assume that the type arguments are provided, and thus the typeReference can be
            // resolved into a valid type
            JetType receiverType = typeResolver.resolveType(scope, typeReference);
            DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor();
            if (declarationDescriptor instanceof ClassDescriptor) {
                ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;

                for (JetTypeProjection typeProjection : userType.getTypeArguments()) {
                    switch (typeProjection.getProjectionKind()) {
                        case IN:
                        case OUT:
                        case STAR:
                            // TODO : Bug in the editor
509
                            trace.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments");
510 511 512 513 514 515 516 517
                            break;
                        case NONE:
                            break;
                    }
                }

                JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
                if (referenceExpression != null) {
518
                    return checkClassConstructorCall(scope, referenceExpression, classDescriptor, receiverType, call);
519 520 521
                }
            }
            else {
522
                trace.getErrorHandler().genericError(((JetElement) call).getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : review the message
523
            }
524
            return null;
525 526 527
        }
        else {
            if (typeElement != null) {
528
                trace.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message
529 530 531 532 533
            }
        }
        return null;
    }

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
    @Nullable
    public JetType checkClassConstructorCall(
            @NotNull JetScope scope,
            @NotNull JetReferenceExpression referenceExpression,
            @NotNull ClassDescriptor classDescriptor,
            @NotNull JetType receiverType,
            @NotNull JetCall call) {
        // When one writes 'new Array<in T>(...)' this does not make much sense, and an instance
        // of 'Array<T>' must be created anyway.
        // Thus, we should either prohibit projections in type arguments in such contexts,
        // or treat them as an automatic upcast to the desired type, i.e. for the user not
        // to be forced to write
        //   val a : Array<in T> = new Array<T>(...)
        // NOTE: Array may be a bad example here, some classes may have substantial functionality
        //       not involving their type parameters
        //
        // The code below upcasts the type automatically

        List<TypeProjection> typeArguments = receiverType.getArguments();

        List<TypeProjection> projectionsStripped = new ArrayList<TypeProjection>();
        for (TypeProjection typeArgument : typeArguments) {
            if (typeArgument.getProjectionKind() != Variance.INVARIANT) {
                projectionsStripped.add(new TypeProjection(typeArgument.getType()));
            }
            else
                projectionsStripped.add(typeArgument);
        }

        FunctionGroup constructors = classDescriptor.getConstructors(projectionsStripped);
564
        OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(null, constructors);
A
Andrey Breslav 已提交
565
        JetType constructorReturnedType = resolveCall(
566 567
                scope,
                wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false),
A
Andrey Breslav 已提交
568
                call);
569 570 571 572 573 574
        if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) {
            DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor();
            assert declarationDescriptor != null;
            trace.recordReferenceResolution(referenceExpression, declarationDescriptor);
            // TODO : more helpful message
            JetArgumentList argumentList = call.getValueArgumentList();
575
            final String errorMessage = "Cannot find a constructor overload for class " + classDescriptor.getName() + " with these arguments";
576
            if (argumentList != null) {
577
                trace.getErrorHandler().genericError(argumentList.getNode(), errorMessage);
578
            }
579
            else {
580
                trace.getErrorHandler().genericError(call.asElement().getNode(), errorMessage);
581
            }
582 583 584 585 586 587 588 589 590
            constructorReturnedType = receiverType;
        }
        // If no upcast needed:
        return constructorReturnedType;

        // Automatic upcast:
//                            result = receiverType;
    }

591 592 593

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

A
Andrey Breslav 已提交
594
    private class TypeInferrerVisitor extends JetVisitor {
595
        protected final JetScope scope;
A
Andrey Breslav 已提交
596
        private final boolean preferBlock;
597
        protected final DataFlowInfo dataFlowInfo;
A
Andrey Breslav 已提交
598

599
        protected JetType result;
600
        protected DataFlowInfo resultDataFlowInfo;
A
Andrey Breslav 已提交
601

602
        private TypeInferrerVisitor(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo) {
A
Andrey Breslav 已提交
603 604
            this.scope = scope;
            this.preferBlock = preferBlock;
605 606 607 608 609 610 611 612 613 614 615
            this.dataFlowInfo = dataFlowInfo;
        }

        @Nullable
        public DataFlowInfo getResultingDataFlowInfo() {
            return resultDataFlowInfo;
        }

        @Nullable
        public JetType getType(@NotNull JetScope scope, @NotNull JetExpression expression, boolean preferBlock) {
            return getType(scope, expression, preferBlock, dataFlowInfo);
A
Andrey Breslav 已提交
616 617
        }

618
        @Nullable
619
        public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo) {
620
            TypeInferrerVisitor visitor;
621
            if (this.scope == scope && this.preferBlock == preferBlock && result == null && dataFlowInfo == this.dataFlowInfo) {
622 623 624
                visitor = this;
            }
            else {
625
                visitor = createNew(scope, preferBlock, dataFlowInfo);
626 627 628 629 630 631
            }
            JetType type = visitor.getType(expression);
            visitor.result = null;
            return type;
        }

632
        @NotNull
633 634
        public TypeInferrerVisitor createNew(JetScope scope, boolean preferBlock, DataFlowInfo dataFlowInfo) {
            return new TypeInferrerVisitor(scope, preferBlock, dataFlowInfo);
635 636
        }

637
        @Nullable
638
        public final JetType getType(@NotNull JetExpression expression) {
639
            assert result == null;
640 641 642
            if (trace.isProcessed(expression)) {
                return trace.getBindingContext().getExpressionType(expression);
            }
643 644
            try {
                expression.accept(this);
645 646 647 648 649
                // Some recursive definitions (object expressions) must put their types in the cache manually:
                if (trace.isProcessed(expression)) {
                    return trace.getBindingContext().getExpressionType(expression);
                }

650 651 652
                if (result instanceof DeferredType) {
                    result = ((DeferredType) result).getActualType();
                }
653 654 655 656 657
                if (result != null) {
                    trace.recordExpressionType(expression, result);
                    if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
                        markDominatedExpressionsAsUnreachable(expression);
                    }
658
                }
659
            }
660 661 662 663
            catch (ReenteringLazyValueComputationException e) {
                trace.getErrorHandler().genericError(expression.getNode(), "Type inference has run into a recursive problem"); // TODO : message
                result = null;
            }
664

665
            trace.markAsProcessed(expression);
A
Andrey Breslav 已提交
666 667 668
            return result;
        }

669 670 671 672
        public void resetResult() {
            result = null;
        }

673 674 675 676 677 678 679
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void markDominatedExpressionsAsUnreachable(JetExpression expression) {
            List<JetElement> dominated = new ArrayList<JetElement>();
            flowInformationProvider.collectDominatedExpressions(expression, dominated);
            Set<JetElement> rootExpressions = JetPsiUtil.findRootExpressions(dominated);
            for (JetElement rootExpression : rootExpressions) {
680
                trace.getErrorHandler().genericError(rootExpression.getNode(),
681 682 683 684
                        "This code is unreachable, because '" + expression.getText() + "' never terminates normally");
            }
        }

A
Andrey Breslav 已提交
685 686
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

A
Andrey Breslav 已提交
687
        @Override
688
        public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
A
Andrey Breslav 已提交
689 690
            // TODO : other members
            // TODO : type substitutions???
691 692 693 694
            String referencedName = expression.getReferencedName();
            if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
                    && referencedName != null) {
                PropertyDescriptor property = scope.getPropertyByFieldReference(referencedName);
A
Andrey Breslav 已提交
695
                if (property == null) {
696
                    trace.getErrorHandler().unresolvedReference(expression);
A
Andrey Breslav 已提交
697 698 699 700 701 702 703 704 705 706 707 708 709 710
                }
                else {
                    trace.recordReferenceResolution(expression, property);
                    result = property.getOutType();
                }
            }
            else {
                assert  expression.getReferencedNameElementType() == JetTokens.IDENTIFIER;
                if (referencedName != null) {
                    VariableDescriptor variable = scope.getVariable(referencedName);
                    if (variable != null) {
                        trace.recordReferenceResolution(expression, variable);
                        result = variable.getOutType();
                        if (result == null) {
711
                            trace.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context");
A
Andrey Breslav 已提交
712
                        }
713
                        return;
A
Andrey Breslav 已提交
714 715 716 717 718
                    }
                    else {
                        ClassifierDescriptor classifier = scope.getClassifier(referencedName);
                        if (classifier != null) {
                            JetType classObjectType = classifier.getClassObjectType();
719
                            if (classObjectType != null && (isNamespacePosition() || classifier.isClassObjectAValue())) {
A
Andrey Breslav 已提交
720 721 722
                                result = classObjectType;
                            }
                            else {
A
Andrey Breslav 已提交
723
                                trace.getErrorHandler().genericError(expression.getNode(), "Classifier " + classifier.getName() +  " does not have a class object");
A
Andrey Breslav 已提交
724 725 726 727 728 729 730
                            }
                            trace.recordReferenceResolution(expression, classifier);
                            return;
                        }
                        else if (furtherNameLookup(expression, referencedName)) {
                            return;
                        }
731
                    }
732
                    trace.getErrorHandler().unresolvedReference(expression);
A
Andrey Breslav 已提交
733 734 735 736
                }
            }
        }

737 738 739 740
        public boolean isNamespacePosition() {
            return false;
        }

741 742 743
        protected boolean furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) {
            NamespaceType namespaceType = lookupNamespaceType(expression, referencedName);
            if (namespaceType != null) {
744
                trace.getErrorHandler().genericError(expression.getNode(), "Expression expected, but a namespace name found");
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
                return true;
            }
            return false;
        }

        @Nullable
        protected NamespaceType lookupNamespaceType(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) {
            NamespaceDescriptor namespace = scope.getNamespace(referencedName);
            if (namespace == null) {
                return null;
            }
            trace.recordReferenceResolution(expression, namespace);
            return namespace.getNamespaceType();
        }

760
        @Override
761 762 763
        public void visitObjectLiteralExpression(final JetObjectLiteralExpression expression) {
            TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, new BindingTraceAdapter(trace) {
                @Override
764
                public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull final DeclarationDescriptor descriptor) {
765
                    if (declaration == expression.getObjectDeclaration()) {
766 767 768 769 770 771
                        JetType defaultType = new DeferredType(new LazyValue<JetType>() {
                            @Override
                            protected JetType compute() {
                                return ((ClassDescriptor) descriptor).getDefaultType();
                            }
                        });
772 773 774 775 776 777 778 779 780
                        result = defaultType;
                        if (!trace.isProcessed(expression)) {
                            recordExpressionType(expression, defaultType);
                            markAsProcessed(expression);
                        }
                    }
                    super.recordDeclarationResolution(declaration, descriptor);
                }
            });
781 782 783
            topDownAnalyzer.processObject(scope, scope.getContainingDeclaration(), expression.getObjectDeclaration());
        }

A
Andrey Breslav 已提交
784 785 786
        @Override
        public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
            if (preferBlock && !expression.hasParameterSpecification()) {
787
                trace.recordBlock(expression);
788
                result = getBlockReturnedType(scope, expression.getBody(), dataFlowInfo);
A
Andrey Breslav 已提交
789 790 791 792 793 794 795 796 797 798 799
                return;
            }

            JetTypeReference receiverTypeRef = expression.getReceiverTypeRef();
            final JetType receiverType;
            if (receiverTypeRef != null) {
                receiverType = typeResolver.resolveType(scope, receiverTypeRef);
            } else {
                receiverType = scope.getThisType();
            }

800 801 802
            FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(
                    scope.getContainingDeclaration(), Collections.<Annotation>emptyList(), "<anonymous>");

A
Andrey Breslav 已提交
803
            List<JetType> parameterTypes = new ArrayList<JetType>();
804 805 806 807
            List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList();
            List<JetParameter> parameters = expression.getParameters();
            for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
                JetParameter parameter = parameters.get(i);
A
Andrey Breslav 已提交
808
                JetTypeReference typeReference = parameter.getTypeReference();
809 810 811 812 813 814 815 816

                JetType type;
                if (typeReference != null) {
                    type = typeResolver.resolveType(scope, typeReference);
                }
                else {
                    trace.getErrorHandler().genericError(parameter.getNode(), "Type inference for parameters is not implemented yet");
                    type = ErrorUtils.createErrorType("Not inferred");
A
Andrey Breslav 已提交
817
                }
818 819 820
                ValueParameterDescriptor valueParameterDescriptor = classDescriptorResolver.resolveValueParameterDescriptor(functionDescriptor, parameter, i, type);
                parameterTypes.add(valueParameterDescriptor.getOutType());
                valueParameterDescriptors.add(valueParameterDescriptor);
A
Andrey Breslav 已提交
821
            }
822 823 824 825 826 827

            JetType effectiveReceiverType = receiverTypeRef == null ? null : receiverType;
            functionDescriptor.initialize(effectiveReceiverType, Collections.<TypeParameterDescriptor>emptyList(), valueParameterDescriptors, null);
            trace.recordDeclarationResolution(expression, functionDescriptor);

            JetTypeReference returnTypeRef = expression.getReturnTypeRef();
A
Andrey Breslav 已提交
828 829 830 831
            JetType returnType;
            if (returnTypeRef != null) {
                returnType = typeResolver.resolveType(scope, returnTypeRef);
            } else {
A
Cleanup  
Andrey Breslav 已提交
832
                WritableScope writableScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler());
833
                for (VariableDescriptor variableDescriptor : valueParameterDescriptors) {
834
                    writableScope.addVariableDescriptor(variableDescriptor);
A
Andrey Breslav 已提交
835 836
                }
                writableScope.setThisType(receiverType);
837
                returnType = getBlockReturnedType(writableScope, expression.getBody(), dataFlowInfo);
A
Andrey Breslav 已提交
838
            }
839
            JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType;
840 841 842
            functionDescriptor.setReturnType(safeReturnType);


843
            result = JetStandardClasses.getFunctionType(Collections.<Annotation>emptyList(), effectiveReceiverType, parameterTypes, safeReturnType);
A
Andrey Breslav 已提交
844 845 846 847
        }

        @Override
        public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
848 849 850 851
            JetExpression inner = expression.getExpression();
            if (inner != null) {
                result = getType(scope, inner, false);
            }
A
Andrey Breslav 已提交
852 853 854 855 856 857 858
        }

        @Override
        public void visitConstantExpression(JetConstantExpression expression) {
            IElementType elementType = expression.getNode().getElementType();
            JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
            if (elementType == JetNodeTypes.INTEGER_CONSTANT) {
859 860
                Object value = expression.getValue();
                if (value == null) {
861
                    trace.getErrorHandler().genericError(expression.getNode(), "Number is of range for Long");
862 863
                }
                else if (value instanceof Long) {
A
Andrey Breslav 已提交
864 865 866 867 868 869
                    result = standardLibrary.getLongType();
                }
                else {
                    result = standardLibrary.getIntType();
                }
                // TODO : other ranges
A
Cleanup  
Andrey Breslav 已提交
870 871
            }
            else if (elementType == JetNodeTypes.LONG_CONSTANT) {
A
Andrey Breslav 已提交
872
                result = standardLibrary.getLongType();
A
Cleanup  
Andrey Breslav 已提交
873 874
            }
            else if (elementType == JetNodeTypes.FLOAT_CONSTANT) {
A
Andrey Breslav 已提交
875 876 877 878 879
                String text = expression.getText();
                assert text.length() > 0;
                char lastChar = text.charAt(text.length() - 1);
                if (lastChar == 'f' || lastChar == 'F') {
                    result = standardLibrary.getFloatType();
A
Cleanup  
Andrey Breslav 已提交
880 881
                }
                else {
A
Andrey Breslav 已提交
882 883
                    result = standardLibrary.getDoubleType();
                }
A
Cleanup  
Andrey Breslav 已提交
884 885
            }
            else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) {
A
Andrey Breslav 已提交
886
                result = standardLibrary.getBooleanType();
A
Cleanup  
Andrey Breslav 已提交
887 888
            }
            else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) {
A
Andrey Breslav 已提交
889
                result = standardLibrary.getCharType();
A
Cleanup  
Andrey Breslav 已提交
890 891
            }
            else if (elementType == JetNodeTypes.STRING_CONSTANT) {
A
Andrey Breslav 已提交
892
                result = standardLibrary.getStringType();
A
Cleanup  
Andrey Breslav 已提交
893 894
            }
            else if (elementType == JetNodeTypes.NULL) {
A
Andrey Breslav 已提交
895
                result = JetStandardClasses.getNullableNothingType();
A
Cleanup  
Andrey Breslav 已提交
896 897
            }
            else {
A
Andrey Breslav 已提交
898 899 900 901 902 903
                throw new IllegalArgumentException("Unsupported constant: " + expression);
            }
        }

        @Override
        public void visitThrowExpression(JetThrowExpression expression) {
A
Andrey Breslav 已提交
904 905 906 907 908
            JetExpression thrownExpression = expression.getThrownExpression();
            if (thrownExpression != null) {
                JetType type = getType(scope, thrownExpression, false);
                // TODO : check that it inherits Throwable
            }
A
Andrey Breslav 已提交
909 910 911 912 913 914
            result = JetStandardClasses.getNothingType();
        }

        @Override
        public void visitReturnExpression(JetReturnExpression expression) {
            JetExpression returnedExpression = expression.getReturnedExpression();
A
Andrey Breslav 已提交
915

A
Andrey Breslav 已提交
916
            if (returnedExpression != null) {
A
Cleanup  
Andrey Breslav 已提交
917
                getType(scope, returnedExpression, false);
A
Andrey Breslav 已提交
918 919
            }

A
Andrey Breslav 已提交
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
            result = JetStandardClasses.getNothingType();
        }

        @Override
        public void visitBreakExpression(JetBreakExpression expression) {
            result = JetStandardClasses.getNothingType();
        }

        @Override
        public void visitContinueExpression(JetContinueExpression expression) {
            result = JetStandardClasses.getNothingType();
        }

        @Override
        public void visitTypeofExpression(JetTypeofExpression expression) {
A
Andrey Breslav 已提交
935 936
            JetType type = safeGetType(scope, expression.getBaseExpression(), false);
            result = semanticServices.getStandardLibrary().getTypeInfoType(type);
A
Andrey Breslav 已提交
937 938 939 940
        }

        @Override
        public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) {
A
Andrey Breslav 已提交
941 942 943 944 945 946 947
            IElementType operationType = expression.getOperationSign().getReferencedNameElementType();
            JetType actualType = getType(scope, expression.getLeft(), false);
            JetTypeReference right = expression.getRight();
            if (right != null) {
                JetType targetType = typeResolver.resolveType(scope, right);
                if (operationType == JetTokens.COLON) {
                    if (actualType != null && !semanticServices.getTypeChecker().isSubtypeOf(actualType, targetType)) {
948
                        trace.getErrorHandler().typeMismatch(expression.getLeft(), targetType, actualType);
A
Andrey Breslav 已提交
949
                    }
A
Andrey Breslav 已提交
950
                    result = targetType;
A
Andrey Breslav 已提交
951
                }
A
Andrey Breslav 已提交
952
                else if (operationType == JetTokens.AS_KEYWORD) {
953
                    checkForCastImpossibility(expression, actualType, targetType);
A
Andrey Breslav 已提交
954 955 956
                    result = targetType;
                }
                else if (operationType == JetTokens.AS_SAFE) {
957
                    checkForCastImpossibility(expression, actualType, targetType);
A
Andrey Breslav 已提交
958
                    result = TypeUtils.makeNullable(targetType);
A
Andrey Breslav 已提交
959 960
                }
                else {
961
                    trace.getErrorHandler().genericError(expression.getOperationSign().getNode(), "Unsupported binary operation");
A
Andrey Breslav 已提交
962
                }
A
Andrey Breslav 已提交
963 964 965
            }
        }

966 967 968 969 970 971
        private void checkForCastImpossibility(JetBinaryExpressionWithTypeRHS expression, JetType actualType, JetType targetType) {
            if (actualType == null) return;

            JetTypeChecker typeChecker = semanticServices.getTypeChecker();
            if (!typeChecker.isSubtypeOf(targetType, actualType)) {
                if (typeChecker.isSubtypeOf(actualType, targetType)) {
972
                    trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed, use ':' instead");
973 974
                }
                else {
975 976
                    // See JET-58 Make 'as never succeeds' a warning, or even never check for Java (external) types
                    trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "This cast can never succeed");
977 978 979 980
                }
            }
            else {
                if (typeChecker.isSubtypeOf(actualType, targetType)) {
981
                    trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed");
982 983 984 985
                }
            }
        }

A
Andrey Breslav 已提交
986
        @Override
987 988 989 990
        public void visitTupleExpression(JetTupleExpression expression) {
            List<JetExpression> entries = expression.getEntries();
            List<JetType> types = new ArrayList<JetType>();
            for (JetExpression entry : entries) {
991
                types.add(safeGetType(scope, entry, false));
992 993 994 995
            }
            // TODO : labels
            result = JetStandardClasses.getTupleType(types);
        }
A
Andrey Breslav 已提交
996

997 998
        @Override
        public void visitThisExpression(JetThisExpression expression) {
A
Andrey Breslav 已提交
999 1000 1001 1002 1003
            JetType thisType = null;
            String labelName = expression.getLabelName();
            if (labelName != null) {
                Collection<DeclarationDescriptor> declarationsByLabel = scope.getDeclarationsByLabel(labelName);
                int size = declarationsByLabel.size();
A
Andrey Breslav 已提交
1004 1005
                final JetSimpleNameExpression targetLabel = expression.getTargetLabel();
                assert targetLabel != null;
A
Andrey Breslav 已提交
1006 1007 1008 1009 1010
                if (size == 1) {
                    DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
                    if (declarationDescriptor instanceof ClassDescriptor) {
                        ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
                        thisType = classDescriptor.getDefaultType();
1011 1012 1013 1014
                    }
                    else if (declarationDescriptor instanceof FunctionDescriptor) {
                        FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
                        thisType = functionDescriptor.getReceiverType();
A
Andrey Breslav 已提交
1015 1016 1017 1018
                    }
                    else {
                        throw new UnsupportedOperationException(); // TODO
                    }
1019 1020
                    trace.recordReferenceResolution(targetLabel, declarationDescriptor);
                    trace.recordReferenceResolution(expression.getThisReference(), declarationDescriptor);
A
Andrey Breslav 已提交
1021 1022
                }
                else if (size == 0) {
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
                    // This uses the info written by the control flow processor
                    PsiElement psiElement = trace.getBindingContext().resolveToDeclarationPsiElement(targetLabel);
                    if (psiElement instanceof JetFunctionLiteralExpression) {
                        DeclarationDescriptor declarationDescriptor = trace.getBindingContext().getDeclarationDescriptor(psiElement);
                        if (declarationDescriptor instanceof FunctionDescriptor) {
                            thisType = ((FunctionDescriptor) declarationDescriptor).getReceiverType();
                            if (thisType == null) {
                                thisType = JetStandardClasses.getNothingType();
                            }
                            else {
                                trace.recordReferenceResolution(targetLabel, declarationDescriptor);
                                trace.recordReferenceResolution(expression.getThisReference(), declarationDescriptor);
                            }
                        }
                        else {
                            trace.getErrorHandler().unresolvedReference(targetLabel);
                        }
                    }
                    else {
                        trace.getErrorHandler().unresolvedReference(targetLabel);
                    }
A
Andrey Breslav 已提交
1044 1045
                }
                else {
A
Andrey Breslav 已提交
1046
                    trace.getErrorHandler().genericError(targetLabel.getNode(), "Ambiguous label");
A
Andrey Breslav 已提交
1047 1048 1049 1050
                }
            }
            else {
                thisType = scope.getThisType();
A
Andrey Breslav 已提交
1051 1052 1053 1054 1055

                DeclarationDescriptor declarationDescriptorForUnqualifiedThis = scope.getDeclarationDescriptorForUnqualifiedThis();
                if (declarationDescriptorForUnqualifiedThis != null) {
                    trace.recordReferenceResolution(expression.getThisReference(), declarationDescriptorForUnqualifiedThis);
                }
A
Andrey Breslav 已提交
1056 1057 1058 1059
            }

            if (thisType != null) {
                if (JetStandardClasses.isNothing(thisType)) {
1060
                    trace.getErrorHandler().genericError(expression.getNode(), "'this' is not defined in this context");
A
Andrey Breslav 已提交
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
                }
                else {
                    JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
                    if (superTypeQualifier != null) {
                        JetTypeElement superTypeElement = superTypeQualifier.getTypeElement();
                        // Errors are reported by the parser
                        if (superTypeElement instanceof JetUserType) {
                            JetUserType typeElement = (JetUserType) superTypeElement;

                            ClassifierDescriptor classifierCandidate = typeResolver.resolveClass(scope, typeElement);
                            if (classifierCandidate instanceof ClassDescriptor) {
                                ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;

                                Collection<? extends JetType> supertypes = thisType.getConstructor().getSupertypes();
1075
                                TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
A
Andrey Breslav 已提交
1076 1077
                                for (JetType declaredSupertype : supertypes) {
                                    if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
1078
                                        result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
A
Andrey Breslav 已提交
1079 1080 1081 1082
                                        break;
                                    }
                                }
                                if (result == null) {
1083
                                    trace.getErrorHandler().genericError(superTypeElement.getNode(), "Not a superclass");
A
Andrey Breslav 已提交
1084
                                }
1085 1086
                            }
                        }
A
Andrey Breslav 已提交
1087 1088
                    } else {
                        result = thisType;
1089
                    }
A
Andrey Breslav 已提交
1090 1091 1092
                    if (result != null) {
                        trace.recordExpressionType(expression.getThisReference(), result);
                    }
A
Andrey Breslav 已提交
1093
                }
A
Andrey Breslav 已提交
1094 1095 1096
            }
        }

1097 1098
        @Override
        public void visitBlockExpression(JetBlockExpression expression) {
1099
            result = getBlockReturnedType(scope, expression.getStatements(), dataFlowInfo);
1100 1101
        }

A
Andrey Breslav 已提交
1102
        @Override
1103
        public void visitWhenExpression(final JetWhenExpression expression) {
A
Andrey Breslav 已提交
1104
            // TODO :change scope according to the bound value in the when header
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114
            final JetExpression subjectExpression = expression.getSubjectExpression();

            JetType subjectType = null;
            if (subjectExpression != null) {
                subjectType = getType(scope, subjectExpression, false);
            }

            // TODO : exhaustive patterns

            for (JetWhenEntry whenEntry : expression.getEntries()) {
1115
                final JetType finalSubjectType = subjectType != null ? subjectType : ErrorUtils.createErrorType("Unknown type");
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
                JetWhenCondition condition = whenEntry.getCondition();
                if (condition != null) {
                    condition.accept(new JetVisitor() {
                        @Override
                        public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
                            JetExpression conditionExpression = condition.getExpression();
                            if (conditionExpression != null) {
                                JetType type = getType(scope, conditionExpression, false);
                                if (type != null && finalSubjectType != null) {
                                    if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(finalSubjectType, type)) == null) {
                                        trace.getErrorHandler().genericError(conditionExpression.getNode(), "This condition can never hold");
                                    }
                                }
                            }
                        }

                        @Override
                        public void visitWhenConditionCall(JetWhenConditionCall condition) {
                            JetExpression callSuffixExpression = condition.getCallSuffixExpression();
1135
                            JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType, semanticServices.getTypeChecker());
1136 1137 1138
                            if (callSuffixExpression != null) {
                                JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false);
                                ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression");
1139
                                checkNullSafety(finalSubjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression));
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
                            }
                        }

                        @Override
                        public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
                            JetExpression rangeExpression = condition.getRangeExpression();
                            if (rangeExpression != null) {
                                checkInExpression(condition.getOperationReference(), subjectExpression, rangeExpression);
                            }
                        }

                        @Override
                        public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
1153 1154 1155 1156
                            JetPattern pattern = condition.getPattern();
                            if (pattern != null) {
                                checkPatternType(pattern, finalSubjectType);
                            }
1157 1158 1159
                        }

                        @Override
1160 1161
                        public void visitJetElement(JetElement element) {
                            trace.getErrorHandler().genericError(element.getNode(), "Unsupported [JetTypeInferrer] : " + element);
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
                        }
                    });
                }
            }

            List<JetType> expressionTypes = new ArrayList<JetType>();
            collectAllReturnTypes(expression, scope, expressionTypes);
            if (!expressionTypes.isEmpty()) {
                result = semanticServices.getTypeChecker().commonSupertype(expressionTypes);
            }
            else {
                trace.getErrorHandler().genericError(expression.getNode(), "Entries required for when-expression"); // TODO : Scope, and maybe this should not an error
            }
A
Andrey Breslav 已提交
1175 1176
        }

1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
        private void checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType) {
            pattern.accept(new JetVisitor() {
                @Override
                public void visitTypePattern(JetTypePattern typePattern) {
                    JetTypeReference typeReference = typePattern.getTypeReference();
                    if (typeReference != null) {
                        JetType type = typeResolver.resolveType(scope, typeReference);
                        checkTypeCompatibility(type, subjectType, typePattern);
                    }
                }

                @Override
                public void visitWildcardPattern(JetWildcardPattern pattern) {
                    // Nothing
                }

                @Override
                public void visitExpressionPattern(JetExpressionPattern pattern) {
                    JetType type = getType(scope, pattern.getExpression(), false);
                    checkTypeCompatibility(type, subjectType, pattern);
                }

                @Override
                public void visitTuplePattern(JetTuplePattern pattern) {
                    List<JetTuplePatternEntry> entries = pattern.getEntries();
                    TypeConstructor typeConstructor = subjectType.getConstructor();
                    if (!JetStandardClasses.getTuple(entries.size()).getTypeConstructor().equals(typeConstructor)
                            || typeConstructor.getParameters().size() != entries.size()) {
1205
                        trace.getErrorHandler().genericError(pattern.getNode(), "Type mismatch: subject is of type " + subjectType + " but the pattern is of type Tuple" + entries.size()); // TODO : message
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
                    }
                    else {
                        for (int i = 0, entriesSize = entries.size(); i < entriesSize; i++) {
                            JetTuplePatternEntry entry = entries.get(i);
                            JetType type = subjectType.getArguments().get(i).getType();

                            // TODO : is a name always allowed, ie for tuple patterns, not decomposer arg lists?
                            ASTNode nameLabelNode = entry.getNameLabelNode();
                            if (nameLabelNode != null) {
                                trace.getErrorHandler().genericError(nameLabelNode, "Unsupported [JetTypeInferrer]");
                            }

                            JetPattern entryPattern = entry.getPattern();
                            if (entryPattern != null) {
                                checkPatternType(entryPattern, type);
                            }
                        }
                    }
                }

1226 1227 1228 1229 1230 1231 1232
                @Override
                public void visitDecomposerPattern(JetDecomposerPattern pattern) {
                    JetType selectorReturnType = getSelectorReturnType(subjectType, pattern.getDecomposerExpression());

                    checkPatternType(pattern.getArgumentList(), selectorReturnType == null ? ErrorUtils.createErrorType("No type") : selectorReturnType);
                }

1233 1234 1235 1236 1237 1238 1239 1240 1241 1242
                private void checkTypeCompatibility(@Nullable JetType type, @NotNull JetType subjectType, @NotNull JetElement reportErrorOn) {
                    if (type == null) {
                        return;
                    }
                    if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) {
                        trace.getErrorHandler().genericError(reportErrorOn.getNode(), "Incompatible types: " + type + " and " + subjectType); // TODO : message
                    }
                }

                @Override
1243 1244
                public void visitJetElement(JetElement element) {
                    trace.getErrorHandler().genericError(element.getNode(), "Unsupported [JetTypeInferrer]");
1245 1246 1247 1248
                }
            });
        }

A
Andrey Breslav 已提交
1249 1250 1251 1252 1253 1254
        @Override
        public void visitTryExpression(JetTryExpression expression) {
            JetExpression tryBlock = expression.getTryBlock();
            List<JetCatchClause> catchClauses = expression.getCatchClauses();
            JetFinallySection finallyBlock = expression.getFinallyBlock();
            List<JetType> types = new ArrayList<JetType>();
1255 1256 1257 1258 1259
            for (JetCatchClause catchClause : catchClauses) {
                JetParameter catchParameter = catchClause.getCatchParameter();
                JetExpression catchBody = catchClause.getCatchBody();
                if (catchParameter != null) {
                    VariableDescriptor variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, catchParameter);
1260
                    if (catchBody != null) {
A
Cleanup  
Andrey Breslav 已提交
1261
                        WritableScope catchScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
1262 1263 1264 1265 1266
                        catchScope.addVariableDescriptor(variableDescriptor);
                        JetType type = getType(catchScope, catchBody, true);
                        if (type != null) {
                            types.add(type);
                        }
1267
                    }
A
Andrey Breslav 已提交
1268 1269
                }
            }
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
            if (finallyBlock != null) {
                types.clear(); // Do not need the list for the check, but need the code above to typecheck catch bodies
                JetType type = getType(scope, finallyBlock.getFinalExpression(), true);
                if (type != null) {
                    types.add(type);
                }
            }
            JetType type = getType(scope, tryBlock, true);
            if (type != null) {
                types.add(type);
            }
            if (types.isEmpty()) {
                result = null;
            }
            else {
                result = semanticServices.getTypeChecker().commonSupertype(types);
            }
A
Andrey Breslav 已提交
1287 1288 1289
        }

        @Override
1290
        public void visitIfExpression(JetIfExpression expression) {
1291 1292
            JetExpression condition = expression.getCondition();
            checkCondition(scope, condition);
1293

1294
            // TODO : change types according to is and null checks
1295
            JetExpression elseBranch = expression.getElse();
1296
            JetExpression thenBranch = expression.getThen();
1297

1298 1299 1300
            DataFlowInfo thenInfo = extractDataFlowInfoFromCondition(condition, true);
            DataFlowInfo elseInfo = extractDataFlowInfoFromCondition(condition, false);

1301 1302
            if (elseBranch == null) {
                if (thenBranch != null) {
1303
                    getType(scope, thenBranch, true, thenInfo);
1304 1305
                    result = JetStandardClasses.getUnitType();
                }
1306
            }
1307
            else if (thenBranch == null) {
1308
                getType(scope, elseBranch, true, elseInfo);
1309 1310 1311
                result = JetStandardClasses.getUnitType();
            }
            else {
1312 1313
                JetType thenType = getType(scope, thenBranch, true, thenInfo);
                JetType elseType = getType(scope, elseBranch, true, elseInfo);
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
                if (thenType == null) {
                    result = elseType;
                }
                else if (elseType == null) {
                    result = thenType;
                }
                else {
                    result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
                }
            }
A
Andrey Breslav 已提交
1324 1325
        }

1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
        private DataFlowInfo extractDataFlowInfoFromCondition(JetExpression condition, final boolean conditionValue) {
            final DataFlowInfo[] result = new DataFlowInfo[] {dataFlowInfo};
            condition.accept(new JetVisitor() {
                @Override
                public void visitBinaryExpression(JetBinaryExpression expression) {
                    IElementType operationToken = expression.getOperationToken();
                    if (operationToken != JetTokens.EQEQ
                            && operationToken != JetTokens.EXCLEQ
                            && operationToken != JetTokens.EQEQEQ
                            && operationToken != JetTokens.EXCLEQEQEQ) {
                        return;
                    }

                    JetExpression left = expression.getLeft();
                    JetExpression right = expression.getRight();
                    if (left instanceof JetConstantExpression) {
                        JetExpression tmp = left;
                        left = right;
                        right = tmp;
                    }

                    if (!(left instanceof JetSimpleNameExpression)) {
                        return;
                    }
                    JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) left;
                    DeclarationDescriptor declarationDescriptor = trace.getBindingContext().resolveReferenceExpression(nameExpression);
                    if (!(declarationDescriptor instanceof VariableDescriptor)) {
                        return;
                    }
                    VariableDescriptor variableDescriptor = (VariableDescriptor) declarationDescriptor;

                    // TODO : validate that DF makes sense for this variable: local, val, internal w/backing field, etc

                    if (!(right instanceof JetConstantExpression)) {
                        return;
                    }
                    JetConstantExpression constantExpression = (JetConstantExpression) right;
                    if (constantExpression.getNode().getElementType() != JetNodeTypes.NULL) {
                        return;
                    }

                    if (operationToken == JetTokens.EQEQ || operationToken == JetTokens.EQEQEQ) {
                        result[0] = dataFlowInfo.equalsToNull(variableDescriptor, !conditionValue);
                    }
                    else if (operationToken == JetTokens.EXCLEQ || operationToken == JetTokens.EXCLEQEQEQ) {
                        result[0] = dataFlowInfo.equalsToNull(variableDescriptor, conditionValue);
                    }
                }
            });
            return result[0];
        }

1378 1379 1380 1381 1382
        private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition) {
            if (condition != null) {
                JetType conditionType = getType(scope, condition, false);

                if (conditionType != null && !isBoolean(conditionType)) {
1383
                    trace.getErrorHandler().genericError(condition.getNode(), "Condition must be of type Boolean, but was of type " + conditionType);
A
Andrey Breslav 已提交
1384 1385 1386 1387 1388
                }
            }
        }

        @Override
1389 1390 1391 1392 1393 1394 1395
        public void visitWhileExpression(JetWhileExpression expression) {
            checkCondition(scope, expression.getCondition());
            JetExpression body = expression.getBody();
            if (body != null) {
                getType(scope, body, true);
            }
            result = JetStandardClasses.getUnitType();
A
Andrey Breslav 已提交
1396 1397 1398
        }

        @Override
1399 1400
        public void visitDoWhileExpression(JetDoWhileExpression expression) {
            JetExpression body = expression.getBody();
A
Andrey Breslav 已提交
1401 1402 1403 1404
            JetScope conditionScope = scope;
            if (body instanceof JetFunctionLiteralExpression) {
                JetFunctionLiteralExpression function = (JetFunctionLiteralExpression) body;
                if (!function.hasParameterSpecification()) {
A
Cleanup  
Andrey Breslav 已提交
1405
                    WritableScope writableScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
A
Andrey Breslav 已提交
1406
                    conditionScope = writableScope;
1407
                    getBlockReturnedTypeWithWritableScope(writableScope, function.getBody(), dataFlowInfo);
A
Andrey Breslav 已提交
1408
                    trace.recordBlock(function);
A
Andrey Breslav 已提交
1409 1410 1411 1412 1413
                } else {
                    getType(scope, body, true);
                }
            }
            else if (body != null) {
A
Cleanup  
Andrey Breslav 已提交
1414
                WritableScope writableScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
A
Andrey Breslav 已提交
1415
                conditionScope = writableScope;
1416
                getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body), dataFlowInfo);
1417 1418 1419 1420 1421 1422 1423 1424 1425
            }
            checkCondition(conditionScope, expression.getCondition());
            result = JetStandardClasses.getUnitType();
        }

        @Override
        public void visitForExpression(JetForExpression expression) {
            JetParameter loopParameter = expression.getLoopParameter();
            JetExpression loopRange = expression.getLoopRange();
1426 1427 1428 1429
            JetType loopRangeType = null;
            if (loopRange != null) {
                loopRangeType = getType(scope, loopRange, false);
            }
1430 1431
            JetType expectedParameterType = null;
            if (loopRangeType != null) {
1432 1433 1434
                expectedParameterType = checkIterableConvention(loopRangeType, loopRange.getNode());
            }

A
Cleanup  
Andrey Breslav 已提交
1435
            WritableScope loopScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
1436 1437 1438

            if (loopParameter != null) {
                JetTypeReference typeReference = loopParameter.getTypeReference();
1439
                VariableDescriptor variableDescriptor;
1440
                if (typeReference != null) {
1441 1442
                    variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, loopParameter);
                    JetType actualParameterType = variableDescriptor.getOutType();
1443 1444 1445
                    if (expectedParameterType != null &&
                            actualParameterType != null &&
                            !semanticServices.getTypeChecker().isSubtypeOf(expectedParameterType, actualParameterType)) {
1446
                        trace.getErrorHandler().genericError(typeReference.getNode(), "The loop iterates over values of type " + expectedParameterType + " but the parameter is declared to be " + actualParameterType);
1447
                    }
1448 1449
                }
                else {
1450 1451
                    if (expectedParameterType == null) {
                        expectedParameterType = ErrorUtils.createErrorType("Error");
1452
                    }
1453
                    variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), loopParameter, expectedParameterType);
1454
                }
1455
                loopScope.addVariableDescriptor(variableDescriptor);
1456 1457
            }

1458 1459 1460 1461
            JetExpression body = expression.getBody();
            if (body != null) {
                getType(loopScope, body, true); // TODO
            }
1462

1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
            result = JetStandardClasses.getUnitType();
        }

        @Nullable
        private JetType checkIterableConvention(@NotNull JetType type, @NotNull ASTNode reportErrorsOn) {
            OverloadResolutionResult iteratorResolutionResult = resolveNoParametersFunction(type, scope, "iterator");
            if (iteratorResolutionResult.isSuccess()) {
                JetType iteratorType = iteratorResolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
                boolean hasNextFunctionSupported = checkHasNextFunctionSupport(reportErrorsOn, iteratorType);
                boolean hasNextPropertySupported = checkHasNextPropertySupport(reportErrorsOn, iteratorType);
1473
                if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) {
1474
                    // TODO : overload resolution rules impose priorities here???
1475
                    trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext()' property");
1476 1477
                }
                else if (!hasNextFunctionSupported && !hasNextPropertySupported) {
1478
                    trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
1479 1480 1481 1482
                }

                OverloadResolutionResult nextResolutionResult = resolveNoParametersFunction(iteratorType, scope, "next");
                if (nextResolutionResult.isAmbiguity()) {
1483
                    trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression");
1484
                } else if (nextResolutionResult.isNothing()) {
1485
                    trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().next()' method");
1486 1487
                } else {
                    return nextResolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
1488 1489 1490
                }
            }
            else {
1491 1492 1493
                String errorMessage = "For-loop range must have an iterator() method";
                if (iteratorResolutionResult.isAmbiguity()) {
                    errorMessage = "Method 'iterator()' is ambiguous for this expression";
1494
                }
1495
                trace.getErrorHandler().genericError(reportErrorsOn, errorMessage);
1496
            }
1497 1498
            return null;
        }
1499

1500 1501 1502
        private boolean checkHasNextFunctionSupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) {
            OverloadResolutionResult hasNextResolutionResult = resolveNoParametersFunction(iteratorType, scope, "hasNext");
            if (hasNextResolutionResult.isAmbiguity()) {
1503
                trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().hasNext()' is ambiguous for this expression");
1504 1505 1506 1507 1508
            } else if (hasNextResolutionResult.isNothing()) {
                return false;
            } else {
                JetType hasNextReturnType = hasNextResolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
                if (!isBoolean(hasNextReturnType)) {
1509
                    trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext()' method of the loop range must return Boolean, but returns " + hasNextReturnType);
1510
                }
1511
            }
1512 1513
            return true;
        }
1514

1515
        private boolean checkHasNextPropertySupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) {
1516
            VariableDescriptor hasNextProperty = iteratorType.getMemberScope().getVariable("hasNext");
1517 1518 1519 1520 1521 1522 1523
            // TODO :extension properties
            if (hasNextProperty == null) {
                return false;
            } else {
                JetType hasNextReturnType = hasNextProperty.getOutType();
                if (hasNextReturnType == null) {
                    // TODO : accessibility
1524
                    trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must be readable");
1525 1526
                }
                else if (!isBoolean(hasNextReturnType)) {
1527
                    trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must return Boolean, but returns " + hasNextReturnType);
1528 1529 1530 1531 1532
                }
            }
            return true;
        }

A
Andrey Breslav 已提交
1533 1534 1535 1536
        @Override
        public void visitNewExpression(JetNewExpression expression) {
            // TODO : type argument inference
            JetTypeReference typeReference = expression.getTypeReference();
1537
            if (typeReference != null) {
1538
                result = checkConstructorCall(scope, typeReference, expression);
1539
            }
A
Andrey Breslav 已提交
1540 1541 1542
        }

        @Override
A
Andrey Breslav 已提交
1543
        public void visitHashQualifiedExpression(JetHashQualifiedExpression expression) {
1544
            trace.getErrorHandler().genericError(expression.getOperationTokenNode(), "Unsupported");
A
Andrey Breslav 已提交
1545 1546 1547 1548
        }

        @Override
        public void visitQualifiedExpression(JetQualifiedExpression expression) {
1549
            // TODO : functions as values
A
Andrey Breslav 已提交
1550
            JetExpression selectorExpression = expression.getSelectorExpression();
1551
            JetExpression receiverExpression = expression.getReceiverExpression();
1552
            JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false, dataFlowInfo).getType(receiverExpression);
A
Andrey Breslav 已提交
1553
            if (receiverType != null) {
A
Andrey Breslav 已提交
1554 1555
                JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
                if (expression.getOperationSign() == JetTokens.QUEST) {
1556
                    if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) {
A
Andrey Breslav 已提交
1557
                        // TODO : more comprehensible error message
1558
                        trace.getErrorHandler().typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType);
A
Andrey Breslav 已提交
1559 1560
                    }
                    result = TypeUtils.makeNullable(receiverType);
A
Andrey Breslav 已提交
1561
                }
A
Andrey Breslav 已提交
1562 1563
                else {
                    result = selectorReturnType;
1564
                }
A
Andrey Breslav 已提交
1565 1566 1567
                if (selectorExpression != null && result != null) {
                    trace.recordExpressionType(selectorExpression, result);
                }
1568 1569 1570
                if (selectorReturnType != null) {
                    // TODO : extensions to 'Any?'
                    assert selectorExpression != null;
1571 1572 1573

                    receiverType = enrichOutType(receiverExpression, receiverType);

1574 1575
                    checkNullSafety(receiverType, expression.getOperationTokenNode(), getCalleeFunctionDescriptor(selectorExpression));
                }
A
Andrey Breslav 已提交
1576 1577 1578
            }
        }

1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590
        private JetType enrichOutType(JetExpression receiverExpression, JetType receiverType) {
            if (receiverExpression instanceof JetSimpleNameExpression) {
                JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) receiverExpression;
                DeclarationDescriptor declarationDescriptor = trace.getBindingContext().resolveReferenceExpression(nameExpression);
                if (declarationDescriptor instanceof VariableDescriptor) {
                    VariableDescriptor variableDescriptor = (VariableDescriptor) declarationDescriptor;
                    return dataFlowInfo.getOutType(variableDescriptor);
                }
            }
            return receiverType;
        }

1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633
        @NotNull
        private FunctionDescriptor getCalleeFunctionDescriptor(@NotNull JetExpression selectorExpression) {
            final FunctionDescriptor[] result = new FunctionDescriptor[1];
            selectorExpression.accept(new JetVisitor() {
                @Override
                public void visitCallExpression(JetCallExpression callExpression) {
                    callExpression.getCalleeExpression().accept(this);
                }

                @Override
                public void visitReferenceExpression(JetReferenceExpression referenceExpression) {
                    DeclarationDescriptor declarationDescriptor = trace.getBindingContext().resolveReferenceExpression(referenceExpression);
                    if (declarationDescriptor instanceof FunctionDescriptor) {
                        result[0] = (FunctionDescriptor) declarationDescriptor;
                    }
                }

                @Override
                public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
                    expression.getArrayExpression().accept(this);
                }

                @Override
                public void visitBinaryExpression(JetBinaryExpression expression) {
                    expression.getLeft().accept(this);
                }

                @Override
                public void visitQualifiedExpression(JetQualifiedExpression expression) {
                    expression.getReceiverExpression().accept(this);
                }

                @Override
                public void visitJetElement(JetElement element) {
                    trace.getErrorHandler().genericError(element.getNode(), "Unsupported [getCalleeFunctionDescriptor]: " + element);
                }
            });
            if (result[0] == null) {
                result[0] = ErrorUtils.createErrorFunction(0, Collections.<JetType>emptyList());
            }
            return result[0];
        }

1634 1635 1636 1637 1638
        private JetType getCallExpressionType(@Nullable JetType receiverType, @NotNull JetCallExpression callExpression) {
            OverloadDomain overloadDomain = getOverloadDomain(receiverType, scope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
            return resolveCall(scope, overloadDomain, callExpression);
        }

A
Andrey Breslav 已提交
1639 1640
        private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) {
            if (selectorExpression instanceof JetCallExpression) {
1641
                return getCallExpressionType(receiverType, (JetCallExpression) selectorExpression);
A
Andrey Breslav 已提交
1642 1643
            }
            else if (selectorExpression instanceof JetSimpleNameExpression) {
1644
                JetScope compositeScope = new ScopeWithReceiver(scope, receiverType, semanticServices.getTypeChecker());
A
Andrey Breslav 已提交
1645 1646 1647 1648
                return getType(compositeScope, selectorExpression, false);
            }
            else if (selectorExpression != null) {
                // TODO : not a simple name -> resolve in scope, expect property type or a function type
1649
                trace.getErrorHandler().genericError(selectorExpression.getNode(), "Unsupported selector element type: " + selectorExpression);
A
Andrey Breslav 已提交
1650 1651 1652 1653
            }
            return receiverType;
        }

A
Andrey Breslav 已提交
1654 1655
        @Override
        public void visitCallExpression(JetCallExpression expression) {
1656
            result = getCallExpressionType(null, expression);
1657
        }
A
Andrey Breslav 已提交
1658

A
Andrey Breslav 已提交
1659 1660 1661
        @Override
        public void visitIsExpression(JetIsExpression expression) {
            // TODO : patterns and everything
A
Andrey Breslav 已提交
1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672
            JetType knownType = getType(scope, expression.getLeftHandSide(), false);
            JetPattern pattern = expression.getPattern();
            if (pattern instanceof JetTypePattern) {
                JetTypePattern typePattern = (JetTypePattern) pattern;
                JetTypeReference typeReference = typePattern.getTypeReference();
                if (typeReference != null && knownType != null) {
                    JetType targetType = typeResolver.resolveType(scope, typeReference);
                    if (!semanticServices.getTypeChecker().isSubtypeOf(targetType, knownType)) {
                        trace.getErrorHandler().genericWarning(expression.getNode(), "Expression always evaluates to false"); // TODO : make an error?
                    }
                }
1673 1674 1675
            }
            else {
                trace.getErrorHandler().genericError(pattern.getNode(), "Unsupported [JetTypeInferrer]");
A
Andrey Breslav 已提交
1676
            }
A
Andrey Breslav 已提交
1677 1678 1679
            result = semanticServices.getStandardLibrary().getBooleanType();
        }

A
Andrey Breslav 已提交
1680
        @Override
1681
        public void visitUnaryExpression(JetUnaryExpression expression) {
A
Andrey Breslav 已提交
1682
            JetSimpleNameExpression operationSign = expression.getOperationSign();
1683 1684 1685 1686 1687
            if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
                // TODO : Some processing for the label?
                result = getType(expression.getBaseExpression());
                return;
            }
A
Andrey Breslav 已提交
1688 1689
            IElementType operationType = operationSign.getReferencedNameElementType();
            String name = unaryOperationNames.get(operationType);
1690
            if (name == null) {
1691
                trace.getErrorHandler().genericError(operationSign.getNode(), "Unknown unary operation");
1692 1693
            }
            else {
A
Andrey Breslav 已提交
1694 1695 1696
                JetType receiverType = getType(scope, expression.getBaseExpression(), false);
                if (receiverType != null) {
                    FunctionDescriptor functionDescriptor = lookupFunction(scope, expression.getOperationSign(), name, receiverType, Collections.<JetType>emptyList(), true);
A
Andrey Breslav 已提交
1697
                    if (functionDescriptor != null) {
A
Andrey Breslav 已提交
1698 1699
                        JetType returnType = functionDescriptor.getUnsubstitutedReturnType();
                        if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
1700 1701 1702 1703 1704
                            if (semanticServices.getTypeChecker().isSubtypeOf(returnType, JetStandardClasses.getUnitType())) {
                                 result = JetStandardClasses.getUnitType();
                            }
                            else {
                                if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) {
1705
                                    trace.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType);
1706 1707 1708
                                }
                                // TODO : Maybe returnType?
                                result = receiverType;
A
Andrey Breslav 已提交
1709 1710 1711 1712
                            }
                        } else {
                            result = returnType;
                        }
A
Andrey Breslav 已提交
1713 1714 1715 1716 1717 1718 1719 1720 1721
                    }
                }
            }
        }

        @Override
        public void visitBinaryExpression(JetBinaryExpression expression) {
            JetSimpleNameExpression operationSign = expression.getOperationReference();

A
Andrey Breslav 已提交
1722 1723 1724
            JetExpression left = expression.getLeft();
            JetExpression right = expression.getRight();

A
Andrey Breslav 已提交
1725 1726
            IElementType operationType = operationSign.getReferencedNameElementType();
            if (operationType == JetTokens.IDENTIFIER) {
1727 1728 1729 1730
                String referencedName = operationSign.getReferencedName();
                if (referencedName != null) {
                    result = getTypeForBinaryCall(expression, referencedName, scope, true);
                }
A
Andrey Breslav 已提交
1731
            }
1732
            else if (binaryOperationNames.containsKey(operationType)) {
A
Andrey Breslav 已提交
1733
                result = getTypeForBinaryCall(expression, binaryOperationNames.get(operationType), scope, true);
A
Andrey Breslav 已提交
1734 1735
            }
            else if (operationType == JetTokens.EQ) {
A
Andrey Breslav 已提交
1736 1737 1738 1739
                visitAssignment(expression);
            }
            else if (assignmentOperationNames.containsKey(operationType)) {
                visitAssignmentOperation(expression);
A
Andrey Breslav 已提交
1740
            }
1741
            else if (comparisonOperations.contains(operationType)) {
A
Andrey Breslav 已提交
1742
                JetType compareToReturnType = getTypeForBinaryCall(expression, "compareTo", scope, true);
A
Andrey Breslav 已提交
1743 1744 1745 1746 1747 1748 1749
                if (compareToReturnType != null) {
                    TypeConstructor constructor = compareToReturnType.getConstructor();
                    JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
                    TypeConstructor intTypeConstructor = standardLibrary.getInt().getTypeConstructor();
                    if (constructor.equals(intTypeConstructor)) {
                        result = standardLibrary.getBooleanType();
                    } else {
1750
                        trace.getErrorHandler().genericError(operationSign.getNode(), "compareTo must return Int, but returns " + compareToReturnType);
A
Andrey Breslav 已提交
1751
                    }
A
Andrey Breslav 已提交
1752
                }
A
Andrey Breslav 已提交
1753
            }
A
Equals  
Andrey Breslav 已提交
1754
            else if (equalsOperations.contains(operationType)) {
A
Andrey Breslav 已提交
1755
                String name = "equals";
1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769
                if (right != null) {
                    JetType leftType = getType(scope, left, false);
                    if (leftType != null) {
                        JetType rightType = getType(scope, right, false);
                        if (rightType != null) {
                            FunctionDescriptor equals = lookupFunction(
                                    scope, operationSign, "equals",
                                    leftType, Collections.singletonList(JetStandardClasses.getNullableAnyType()), false);
                            if (equals != null) {
                                if (ensureBooleanResult(operationSign, name, equals.getUnsubstitutedReturnType())) {
                                    ensureNonemptyIntersectionOfOperandTypes(expression);
                                }
                            }
                            else {
1770
                                trace.getErrorHandler().genericError(operationSign.getNode(), "No method 'equals(Any?) : Boolean' available");
1771 1772 1773 1774 1775
                            }
                        }
                    }
                }
                result = semanticServices.getStandardLibrary().getBooleanType();
1776 1777 1778 1779 1780 1781
            }
            else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
                ensureNonemptyIntersectionOfOperandTypes(expression);

                // TODO : Check comparison pointlessness
                result = semanticServices.getStandardLibrary().getBooleanType();
A
Andrey Breslav 已提交
1782 1783 1784
            }
            else if (inOperations.contains(operationType)) {
                if (right == null) {
A
rename  
Andrey Breslav 已提交
1785
                    result = ErrorUtils.createErrorType("No right argument"); // TODO
A
Andrey Breslav 已提交
1786
                    return;
A
Andrey Breslav 已提交
1787
                }
1788
                checkInExpression(operationSign, left, right);
1789
                result = semanticServices.getStandardLibrary().getBooleanType();
A
Equals  
Andrey Breslav 已提交
1790
            }
A
Andrey Breslav 已提交
1791 1792 1793 1794
            else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) {
                JetType leftType = getType(scope, left, false);
                JetType rightType = right == null ? null : getType(scope, right, false);
                if (leftType != null && !isBoolean(leftType)) {
1795
                    trace.getErrorHandler().typeMismatch(left, semanticServices.getStandardLibrary().getBooleanType(), leftType);
A
Andrey Breslav 已提交
1796 1797
                }
                if (rightType != null && !isBoolean(rightType)) {
1798
                    trace.getErrorHandler().typeMismatch(right, semanticServices.getStandardLibrary().getBooleanType(), rightType);
A
Andrey Breslav 已提交
1799 1800 1801
                }
                result = semanticServices.getStandardLibrary().getBooleanType();
            }
A
Andrey Breslav 已提交
1802 1803 1804 1805 1806
            else if (operationType == JetTokens.ELVIS) {
                JetType leftType = getType(scope, left, false);
                JetType rightType = right == null ? null : getType(scope, right, false);
                if (leftType != null) {
                    if (!leftType.isNullable()) {
1807
                        trace.getErrorHandler().genericWarning(left.getNode(), "Elvis operator (?:) is always returns the left operand of non-nullable type " + leftType);
A
Andrey Breslav 已提交
1808 1809 1810 1811 1812 1813
                    }
                    if (rightType != null) {
                        result = TypeUtils.makeNullableAsSpecified(semanticServices.getTypeChecker().commonSupertype(leftType, rightType), rightType.isNullable());
                    }
                }
            }
A
Equals  
Andrey Breslav 已提交
1814
            else {
1815
                trace.getErrorHandler().genericError(operationSign.getNode(), "Unknown operation");
A
Andrey Breslav 已提交
1816 1817 1818
            }
        }

1819 1820 1821 1822 1823 1824
        private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right) {
            String name = "contains";
            JetType containsType = getTypeForBinaryCall(scope, right, operationSign, left, name, true);
            ensureBooleanResult(operationSign, name, containsType);
        }

1825 1826 1827 1828 1829 1830 1831
        private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression) {
            JetSimpleNameExpression operationSign = expression.getOperationReference();
            JetExpression left = expression.getLeft();
            JetExpression right = expression.getRight();

            // TODO : duplicated effort for == and !=
            JetType leftType = getType(scope, left, false);
1832
            if (leftType != null && right != null) {
1833 1834
                JetType rightType = getType(scope, right, false);

1835 1836 1837
                if (rightType != null) {
                    JetType intersect = TypeUtils.intersect(semanticServices.getTypeChecker(), new HashSet<JetType>(Arrays.asList(leftType, rightType)));
                    if (intersect == null) {
1838
                        trace.getErrorHandler().genericError(expression.getNode(), "Operator " + operationSign.getReferencedName() + " cannot be applied to " + leftType + " and " + rightType);
1839
                    }
1840 1841 1842 1843
                }
            }
        }

A
Andrey Breslav 已提交
1844 1845 1846 1847 1848 1849 1850 1851 1852
        protected void visitAssignmentOperation(JetBinaryExpression expression) {
            assignmentIsNotAnExpressionError(expression);
        }

        protected void visitAssignment(JetBinaryExpression expression) {
            assignmentIsNotAnExpressionError(expression);
        }

        private void assignmentIsNotAnExpressionError(JetBinaryExpression expression) {
1853
            trace.getErrorHandler().genericError(expression.getNode(), "Assignments are not expressions, and only expressions are allowed in this context");
A
Andrey Breslav 已提交
1854 1855
        }

1856 1857 1858 1859 1860
        private boolean ensureBooleanResult(JetExpression operationSign, String name, JetType resultType) {
            return ensureBooleanResultWithCustomSubject(operationSign, resultType, "'" + name + "'");
        }

        private boolean ensureBooleanResultWithCustomSubject(JetExpression operationSign, JetType resultType, String subjectName) {
A
Andrey Breslav 已提交
1861 1862
            if (resultType != null) {
                // TODO : Relax?
A
Andrey Breslav 已提交
1863
                if (!isBoolean(resultType)) {
1864
                    trace.getErrorHandler().genericError(operationSign.getNode(), subjectName + " must return Boolean but returns " + resultType);
1865
                    return false;
A
Andrey Breslav 已提交
1866 1867
                }
            }
1868
            return true;
A
Andrey Breslav 已提交
1869 1870
        }

A
Andrey Breslav 已提交
1871
        private boolean isBoolean(@NotNull JetType type) {
A
Andrey Breslav 已提交
1872
            return semanticServices.getTypeChecker().isConvertibleTo(type,  semanticServices.getStandardLibrary().getBooleanType());
A
Andrey Breslav 已提交
1873 1874
        }

1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
        @Nullable
        protected List<JetType> getTypes(JetScope scope, List<JetExpression> indexExpressions) {
            List<JetType> argumentTypes = new ArrayList<JetType>();
            TypeInferrerVisitor typeInferrerVisitor = new TypeInferrerVisitor(scope, false, dataFlowInfo);
            for (JetExpression indexExpression : indexExpressions) {
                JetType type = typeInferrerVisitor.getType(indexExpression);
                if (type == null) {
                    return null;
                }
                argumentTypes.add(type);
                typeInferrerVisitor.resetResult(); // TODO : recreate?
            }
            return argumentTypes;
        }

A
Andrey Breslav 已提交
1890 1891 1892 1893 1894 1895 1896 1897
        @Override
        public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
            JetExpression arrayExpression = expression.getArrayExpression();
            JetType receiverType = getType(scope, arrayExpression, false);
            List<JetExpression> indexExpressions = expression.getIndexExpressions();
            List<JetType> argumentTypes = getTypes(scope, indexExpressions);
            if (argumentTypes == null) return;

1898 1899 1900 1901 1902
            if (receiverType != null) {
                FunctionDescriptor functionDescriptor = lookupFunction(scope, expression, "get", receiverType, argumentTypes, true);
                if (functionDescriptor != null) {
                    result = functionDescriptor.getUnsubstitutedReturnType();
                }
A
Andrey Breslav 已提交
1903 1904 1905
            }
        }

1906
        @Nullable
1907 1908 1909 1910 1911
        protected JetType getTypeForBinaryCall(
                @NotNull JetBinaryExpression expression,
                @NotNull String name,
                @NotNull JetScope scope,
                boolean reportUnresolved) {
A
Andrey Breslav 已提交
1912 1913 1914
            JetExpression left = expression.getLeft();
            JetExpression right = expression.getRight();
            if (right == null) {
1915
                return null;
A
Andrey Breslav 已提交
1916
            }
A
Andrey Breslav 已提交
1917 1918 1919 1920
            JetSimpleNameExpression operationSign = expression.getOperationReference();
            return getTypeForBinaryCall(scope, left, operationSign, right, name, reportUnresolved);
        }

1921
        @Nullable
1922 1923 1924 1925 1926 1927 1928 1929 1930 1931
        private JetType getTypeForBinaryCall(
                @NotNull JetScope scope,
                @NotNull JetExpression left,
                @NotNull JetSimpleNameExpression operationSign,
                @NotNull JetExpression right,
                @NotNull String name,
                boolean reportUnresolved) {
            JetType leftType = getType(scope, left, false);
            JetType rightType = getType(scope, right, false);
            if (leftType == null || rightType == null) {
1932 1933
                return null;
            }
A
Andrey Breslav 已提交
1934
            FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType), reportUnresolved);
A
Andrey Breslav 已提交
1935
            if (functionDescriptor != null) {
1936 1937
                if (leftType.isNullable()) {
                    // TODO : better error message for '1 + nullableVar' case
1938
                    trace.getErrorHandler().genericError(operationSign.getNode(),
1939 1940 1941 1942 1943 1944
                            "Infix call corresponds to a dot-qualified call '" +
                            left.getText() + "." + name + "(" + right.getText() + ")'" +
                            " which is not allowed on a nullable receiver '" + right.getText() + "'." +
                            " Use '?.'-qualified call instead");
                }

A
Andrey Breslav 已提交
1945 1946 1947 1948
                return functionDescriptor.getUnsubstitutedReturnType();
            }
            return null;
        }
A
Andrey Breslav 已提交
1949 1950 1951

        @Override
        public void visitDeclaration(JetDeclaration dcl) {
1952
            trace.getErrorHandler().genericError(dcl.getNode(), "Declarations are not allowed in this position");
A
Andrey Breslav 已提交
1953 1954
        }

1955 1956
        @Override
        public void visitRootNamespaceExpression(JetRootNamespaceExpression expression) {
1957
            trace.getErrorHandler().genericError(expression.getNode(), "'namespace' is not an expression");
1958 1959 1960
            result = null;
        }

A
Andrey Breslav 已提交
1961
        @Override
1962 1963
        public void visitJetElement(JetElement element) {
            trace.getErrorHandler().genericError(element.getNode(), "[JetTypeInferrer] Unsupported element: " + element + " " + element.getClass().getCanonicalName());
A
Andrey Breslav 已提交
1964 1965 1966
        }
    }

1967
    private class TypeInferrerVisitorWithNamespaces extends TypeInferrerVisitor {
1968 1969
        private TypeInferrerVisitorWithNamespaces(@NotNull JetScope scope, boolean preferBlock, DataFlowInfo dataFlowInfo) {
            super(scope, preferBlock, dataFlowInfo);
1970 1971
        }

1972 1973 1974 1975 1976
        @Override
        public boolean isNamespacePosition() {
            return true;
        }

1977 1978
        @NotNull
        @Override
1979 1980
        public TypeInferrerVisitor createNew(JetScope scope, boolean preferBlock, DataFlowInfo dataFlowInfo) {
            return new TypeInferrerVisitorWithNamespaces(scope, preferBlock, dataFlowInfo);
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995
        }

        @Override
        public void visitRootNamespaceExpression(JetRootNamespaceExpression expression) {
            result = JetModuleUtil.getRootNamespaceType(expression);
        }

        @Override
        protected boolean furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) {
            result = lookupNamespaceType(expression, referencedName);
            return result != null;
        }

    }

A
Andrey Breslav 已提交
1996 1997 1998
    private class TypeInferrerVisitorWithWritableScope extends TypeInferrerVisitor {
        private final WritableScope scope;

1999 2000
        public TypeInferrerVisitorWithWritableScope(@NotNull WritableScope scope, boolean preferBlock, DataFlowInfo dataFlowInfo) {
            super(scope, preferBlock, dataFlowInfo);
A
Andrey Breslav 已提交
2001 2002 2003
            this.scope = scope;
        }

A
Andrey Breslav 已提交
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
        @Override
        public void visitObjectDeclaration(JetObjectDeclaration declaration) {
            TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, trace);
            topDownAnalyzer.processObject(scope, scope.getContainingDeclaration(), declaration);
            ClassDescriptor classDescriptor = trace.getBindingContext().getClassDescriptor(declaration);
            if (classDescriptor != null) {
                PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolveObjectDeclarationAsPropertyDescriptor(scope.getContainingDeclaration(), declaration, classDescriptor);
                scope.addVariableDescriptor(propertyDescriptor);
            }
        }

A
Andrey Breslav 已提交
2015 2016
        @Override
        public void visitProperty(JetProperty property) {
2017

2018 2019 2020 2021 2022
            JetTypeReference receiverTypeRef = property.getReceiverTypeRef();
            if (receiverTypeRef != null) {
                trace.getErrorHandler().genericError(receiverTypeRef.getNode(), "Local receiver-properties are not allowed");
            }

2023 2024
            JetPropertyAccessor getter = property.getGetter();
            if (getter != null) {
2025
                trace.getErrorHandler().genericError(getter.getNode(), "Local variables are not allowed to have getters");
2026 2027 2028 2029
            }

            JetPropertyAccessor setter = property.getSetter();
            if (setter != null) {
2030
                trace.getErrorHandler().genericError(setter.getNode(), "Local variables are not allowed to have setters");
2031 2032
            }

2033
            VariableDescriptor propertyDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, property);
2034 2035 2036 2037 2038 2039 2040
            JetExpression initializer = property.getInitializer();
            if (property.getPropertyTypeRef() != null && initializer != null) {
                JetType initializerType = getType(scope, initializer, false);
                JetType outType = propertyDescriptor.getOutType();
                if (outType != null &&
                    initializerType != null &&
                    !semanticServices.getTypeChecker().isConvertibleTo(initializerType, outType)) {
2041
                    trace.getErrorHandler().typeMismatch(initializer, outType, initializerType);
2042 2043 2044
                }
            }

2045
            scope.addVariableDescriptor(propertyDescriptor);
A
Andrey Breslav 已提交
2046 2047 2048 2049
        }

        @Override
        public void visitFunction(JetFunction function) {
2050
            scope.addFunctionDescriptor(classDescriptorResolver.resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function));
A
Andrey Breslav 已提交
2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082
        }

        @Override
        public void visitClass(JetClass klass) {
            super.visitClass(klass); // TODO
        }

        @Override
        public void visitExtension(JetExtension extension) {
            super.visitExtension(extension); // TODO
        }

        @Override
        public void visitTypedef(JetTypedef typedef) {
            super.visitTypedef(typedef); // TODO
        }

        @Override
        public void visitDeclaration(JetDeclaration dcl) {
            visitJetElement(dcl);
        }

        @Override
        protected void visitAssignmentOperation(JetBinaryExpression expression) {
            IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
            String name = assignmentOperationNames.get(operationType);
            JetType assignmentOperationType = getTypeForBinaryCall(expression, name, scope, false);

            if (assignmentOperationType == null) {
                String counterpartName = binaryOperationNames.get(assignmentOperationCounterparts.get(operationType));
                getTypeForBinaryCall(expression, counterpartName, scope, true);
            }
2083
            result = null; // not an expression
A
Andrey Breslav 已提交
2084 2085 2086 2087 2088
        }

        @Override
        protected void visitAssignment(JetBinaryExpression expression) {
            JetExpression left = expression.getLeft();
2089
            JetExpression deparenthesized = JetPsiUtil.deparenthesize(left);
A
Andrey Breslav 已提交
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101
            JetExpression right = expression.getRight();
            if (deparenthesized instanceof JetArrayAccessExpression) {
                JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) deparenthesized;
                resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference());
            }
            else {
                JetType leftType = getType(scope, left, false);
                if (right != null) {
                    JetType rightType = getType(scope, right, false);
                    if (rightType != null &&
                        leftType != null &&
                            !semanticServices.getTypeChecker().isConvertibleTo(rightType, leftType)) {
2102
                        trace.getErrorHandler().typeMismatch(right, leftType, rightType);
A
Andrey Breslav 已提交
2103 2104 2105
                    }
                }
            }
A
Andrey Breslav 已提交
2106
            result = null; // This is not an element
A
Andrey Breslav 已提交
2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127
        }

        private void resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign) {
            List<JetType> argumentTypes = getTypes(scope, arrayAccessExpression.getIndexExpressions());
            if (argumentTypes == null) return;
            JetType rhsType = getType(scope, rightHandSide, false);
            if (rhsType == null) return;
            argumentTypes.add(rhsType);

            JetType receiverType = getType(scope, arrayAccessExpression.getArrayExpression(), false);
            if (receiverType == null) return;

            // TODO : nasty hack: effort is duplicated
            lookupFunction(scope, arrayAccessExpression, "set", receiverType, argumentTypes, true);
            FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, "set", receiverType, argumentTypes, true);
            if (functionDescriptor != null) {
                result = functionDescriptor.getUnsubstitutedReturnType();
            }
        }

        @Override
2128 2129
        public void visitJetElement(JetElement element) {
            trace.getErrorHandler().genericError(element.getNode(), "Unsupported element in a block: " + element + " " + element.getClass().getCanonicalName());
A
Andrey Breslav 已提交
2130
        }
2131

A
Andrey Breslav 已提交
2132
    }
A
Andrey Breslav 已提交
2133

2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145
//    private class CachedBindingTrace extends BindingTraceAdapter {
//
//        public CachedBindingTrace(BindingTrace originalTrace) {
//            super(originalTrace);
//        }
//
//        @Override
//        public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) {
//            super.recordExpressionType(expression, type);
//            typeCache.put(expression, type);
//        }
//    }
2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163

    private static class TypeAndDataFlowInfo {
        private final JetType type;
        private final DataFlowInfo dataFlowInfo;

        private TypeAndDataFlowInfo(JetType type, DataFlowInfo dataFlowInfo) {
            this.type = type;
            this.dataFlowInfo = dataFlowInfo;
        }

        public JetType getType() {
            return type;
        }

        public DataFlowInfo getDataFlowInfo() {
            return dataFlowInfo;
        }
    }
2164
}