JetTypeInferrer.java 88.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.Sets;
5
import com.intellij.lang.ASTNode;
6
import com.intellij.psi.PsiElement;
7 8 9 10 11
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;
12
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
A
Andrey Breslav 已提交
13
import org.jetbrains.jet.lang.descriptors.*;
14 15 16
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lexer.JetTokens;
17
import org.jetbrains.jet.resolve.DescriptorRenderer;
18 19 20 21 22 23 24 25

import java.util.*;

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

D
Dmitry Jemerov 已提交
26 27 28 29 30 31 32
    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 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

    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 已提交
49
    public static final Map<IElementType, String> assignmentOperationNames = new HashMap<IElementType, String>();
A
Andrey Breslav 已提交
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
    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);
    }

67
//    private final Map<JetExpression, JetType> typeCache = new HashMap<JetExpression, JetType>();
68

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).getType(expression);
95 96
    }

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

101
    @Nullable
A
Andrey Breslav 已提交
102 103
    private List<JetType> getTypes(JetScope scope, List<JetExpression> indexExpressions) {
        List<JetType> argumentTypes = new ArrayList<JetType>();
104
        TypeInferrerVisitor typeInferrerVisitor = new TypeInferrerVisitor(scope, false);
105
        for (JetExpression indexExpression : indexExpressions) {
106
            JetType type = typeInferrerVisitor.getType(indexExpression);
107 108 109 110
            if (type == null) {
                return null;
            }
            argumentTypes.add(type);
111
            typeInferrerVisitor.resetResult(); // TODO : recreate?
112 113 114 115
        }
        return argumentTypes;
    }

116 117 118 119 120 121 122 123 124 125
    @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);
        overloadDomain = wrapForTracing(overloadDomain, reference, null, reportUnresolved);
126 127
        OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<JetType>emptyList(), argumentTypes);
        return resolutionResult.isSuccess() ? resolutionResult.getFunctionDescriptor() : null;
128 129 130 131 132 133 134
    }

    private OverloadDomain getOverloadDomain(
            @NotNull final JetScope scope,
            @NotNull JetExpression calleeExpression,
            @Nullable PsiElement argumentList
    ) {
135
        final OverloadDomain[] result = new OverloadDomain[1];
136
        final JetSimpleNameExpression[] reference = new JetSimpleNameExpression[1];
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
        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) {
                // . or ?.
A
Andrey Breslav 已提交
154
                JetType receiverType = getType(scope, expression.getReceiverExpression(), false);
155
                checkNullSafety(receiverType, expression.getOperationTokenNode());
A
Andrey Breslav 已提交
156

157
                JetExpression selectorExpression = expression.getSelectorExpression();
158 159
                if (selectorExpression instanceof JetSimpleNameExpression) {
                    JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression;
160
                    String referencedName = referenceExpression.getReferencedName();
161

162 163
                    if (receiverType != null && referencedName != null) {
                        result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
164 165
                        reference[0] = referenceExpression;
                    }
166 167 168 169 170 171
                } else {
                    throw new UnsupportedOperationException(); // TODO
                }
            }

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

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

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

195
    private void checkNullSafety(JetType receiverType, ASTNode operationTokenNode) {
A
Andrey Breslav 已提交
196
        if (receiverType != null) {
197 198
            boolean namespaceType = receiverType instanceof NamespaceType;
            boolean nullable = !namespaceType && receiverType.isNullable();
199 200 201
            IElementType operationSign = operationTokenNode.getElementType();
            if (nullable && operationSign == JetTokens.DOT) {
                trace.getErrorHandler().genericError(operationTokenNode, "Only safe calls (?.) are allowed on a nullable receiver of type " + receiverType);
A
Andrey Breslav 已提交
202
            }
203
            else if (!nullable && operationSign == JetTokens.SAFE_ACCESS) {
204
                if (namespaceType) {
205
                    trace.getErrorHandler().genericError(operationTokenNode, "Safe calls are not allowed on namespaces");
206 207
                }
                else {
208
                    trace.getErrorHandler().genericWarning(operationTokenNode, "Unnecessary safe call on a non-null receiver of type  " + receiverType);
209
                }
A
Andrey Breslav 已提交
210 211 212 213
            }
        }
    }

214 215
    private OverloadDomain wrapForTracing(
            @Nullable final OverloadDomain overloadDomain,
216
            final JetReferenceExpression referenceExpression,
217
            @Nullable final PsiElement argumentList,
218
            final boolean reportErrors) {
219
        if (overloadDomain == null) return OverloadDomain.EMPTY;
220
        assert referenceExpression != null;
221
        return new OverloadDomain() {
222
            @NotNull
223
            @Override
224 225 226 227
            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;
228 229
            }

230
            @NotNull
231
            @Override
232 233 234 235 236 237 238 239 240 241 242 243 244
            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:
245
                            trace.getErrorHandler().unresolvedReference(referenceExpression);
246 247 248 249
                            break;
                        case SINGLE_FUNCTION_ARGUMENT_MISMATCH:
                            if (argumentList != null) {
                                // TODO : More helpful message. NOTE: there's a separate handling for this for constructors
250
                                trace.getErrorHandler().genericError(argumentList.getNode(), "Arguments do not match " + DescriptorRenderer.TEXT.render(resolutionResult.getFunctionDescriptor()));
251 252
                            }
                            else {
253
                                trace.getErrorHandler().unresolvedReference(referenceExpression);
254 255 256 257 258
                            }
                            break;
                        case AMBIGUITY:
                            if (argumentList != null) {
                                // TODO : More helpful message. NOTE: there's a separate handling for this for constructors
259
                                trace.getErrorHandler().genericError(argumentList.getNode(), "Overload ambiguity [TODO : more helpful message]");
260 261
                            }
                            else {
262
                                trace.getErrorHandler().unresolvedReference(referenceExpression);
263 264 265 266
                            }
                            break;
                        default:
                            // Not a success
267
                    }
A
Andrey Breslav 已提交
268
                }
269 270 271 272 273
            }

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

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

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

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

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

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

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

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

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

A
Andrey Breslav 已提交
365 366
        JetType result = null;
        for (JetElement statement : block) {
367 368 369
            trace.recordStatement(statement);
            JetExpression statementExpression = (JetExpression) statement;
            result = blockLevelVisitor.getType(statementExpression);
A
Andrey Breslav 已提交
370
            blockLevelVisitor.resetResult(); // TODO : maybe it's better to recreate the visitors with the same scope?
371
        }
A
Andrey Breslav 已提交
372
        return result;
373 374
    }

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

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
    @Nullable
    private JetType resolveOverloads(JetScope scope, JetCallExpression expression, OverloadDomain overloadDomain) {
        List<JetTypeProjection> typeArguments = expression.getTypeArguments();
        List<JetArgument> valueArguments = expression.getValueArguments();
        List<JetExpression> functionLiteralArguments = expression.getFunctionLiteralArguments();
        return resolveOverloads(scope, overloadDomain, typeArguments, valueArguments, functionLiteralArguments);
    }

    @Nullable
    private JetType resolveOverloads(
            @NotNull JetScope scope,
            @NotNull OverloadDomain overloadDomain,
            @NotNull List<JetTypeProjection> typeArguments,
            @NotNull List<JetArgument> valueArguments,
            @NotNull List<JetExpression> functionLiteralArguments) {
        // 1) ends with a name -> (scope, name) to look up
        // 2) ends with something else -> just check types

        for (JetTypeProjection typeArgument : typeArguments) {
            if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
412
                trace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
            }
        }

        boolean someNamed = false;
        for (JetArgument argument : valueArguments) {
            if (argument.isNamed()) {
                someNamed = true;
                break;
            }
        }

//                JetExpression functionLiteralArgument = functionLiteralArguments.isEmpty() ? null : functionLiteralArguments.get(0);
        // 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 {
            List<JetType> types = new ArrayList<JetType>();
            for (JetTypeProjection projection : typeArguments) {
                // TODO : check that there's no projection
                JetTypeReference typeReference = projection.getTypeReference();
                if (typeReference != null) {
                    types.add(typeResolver.resolveType(scope, typeReference));
                }
            }

            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));
            }

            OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
            if (resolutionResult.isSuccess()) {
                return resolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
            }
        }
        return null;
    }

    @Nullable
467
    public JetType checkConstructorCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) {
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
        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
487
                            trace.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments");
488 489 490 491 492 493 494 495
                            break;
                        case NONE:
                            break;
                    }
                }

                JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
                if (referenceExpression != null) {
496
                    return checkClassConstructorCall(scope, referenceExpression, classDescriptor, receiverType, call);
497 498 499
                }
            }
            else {
500
                trace.getErrorHandler().genericError(((JetElement) call).getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : review the message
501
            }
502
            return null;
503 504 505
        }
        else {
            if (typeElement != null) {
506
                trace.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message
507 508 509 510 511
            }
        }
        return null;
    }

512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
    @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);
        OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors);
        JetType constructorReturnedType = resolveOverloads(
                scope,
                wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false),
                Collections.<JetTypeProjection>emptyList(),
                call.getValueArguments(),
                call.getFunctionLiteralArguments());
        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();
            if (argumentList != null) {
556
                trace.getErrorHandler().genericError(argumentList.getNode(), "Cannot find an overload for these arguments");
557 558 559 560 561 562 563 564 565 566
            }
            constructorReturnedType = receiverType;
        }
        // If no upcast needed:
        return constructorReturnedType;

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

567 568 569

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

A
Andrey Breslav 已提交
570
    private class TypeInferrerVisitor extends JetVisitor {
571
        protected final JetScope scope;
A
Andrey Breslav 已提交
572
        private final boolean preferBlock;
A
Andrey Breslav 已提交
573

574
        protected JetType result;
A
Andrey Breslav 已提交
575

576
        private TypeInferrerVisitor(@NotNull JetScope scope, boolean preferBlock) {
A
Andrey Breslav 已提交
577 578 579 580
            this.scope = scope;
            this.preferBlock = preferBlock;
        }

581 582 583 584 585 586 587
        @Nullable
        public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
            TypeInferrerVisitor visitor;
            if (this.scope == scope && this.preferBlock == preferBlock && result == null) {
                visitor = this;
            }
            else {
588
                visitor = createNew(scope, preferBlock);
589 590 591 592 593 594
            }
            JetType type = visitor.getType(expression);
            visitor.result = null;
            return type;
        }

595 596 597 598 599
        @NotNull
        public TypeInferrerVisitor createNew(JetScope scope, boolean preferBlock) {
            return new TypeInferrerVisitor(scope, preferBlock);
        }

600
        @Nullable
601
        public final JetType getType(@NotNull JetExpression expression) {
602
            assert result == null;
603 604 605
            if (trace.isProcessed(expression)) {
                return trace.getBindingContext().getExpressionType(expression);
            }
606 607
            try {
                expression.accept(this);
608 609 610
                if (result instanceof DeferredType) {
                    result = ((DeferredType) result).getActualType();
                }
611 612 613 614 615
                if (result != null) {
                    trace.recordExpressionType(expression, result);
                    if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
                        markDominatedExpressionsAsUnreachable(expression);
                    }
616
                }
617
            }
618 619 620 621
            catch (ReenteringLazyValueComputationException e) {
                trace.getErrorHandler().genericError(expression.getNode(), "Type inference has run into a recursive problem"); // TODO : message
                result = null;
            }
622

623
            trace.markAsProcessed(expression);
A
Andrey Breslav 已提交
624 625 626
            return result;
        }

627 628 629 630
        public void resetResult() {
            result = null;
        }

631 632 633 634 635 636 637
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        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) {
638
                trace.getErrorHandler().genericError(rootExpression.getNode(),
639 640 641 642
                        "This code is unreachable, because '" + expression.getText() + "' never terminates normally");
            }
        }

A
Andrey Breslav 已提交
643 644
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

A
Andrey Breslav 已提交
645
        @Override
646
        public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
A
Andrey Breslav 已提交
647 648
            // TODO : other members
            // TODO : type substitutions???
649 650 651 652
            String referencedName = expression.getReferencedName();
            if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
                    && referencedName != null) {
                PropertyDescriptor property = scope.getPropertyByFieldReference(referencedName);
A
Andrey Breslav 已提交
653
                if (property == null) {
654
                    trace.getErrorHandler().unresolvedReference(expression);
A
Andrey Breslav 已提交
655 656 657 658 659 660 661 662 663 664 665 666 667 668
                }
                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) {
669
                            trace.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context");
A
Andrey Breslav 已提交
670
                        }
671
                        return;
672 673
                    } else if (furtherNameLookup(expression, referencedName)) {
                        return;
674
                    }
675
                    trace.getErrorHandler().unresolvedReference(expression);
A
Andrey Breslav 已提交
676 677 678 679
                }
            }
        }

680 681 682
        protected boolean furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) {
            NamespaceType namespaceType = lookupNamespaceType(expression, referencedName);
            if (namespaceType != null) {
683
                trace.getErrorHandler().genericError(expression.getNode(), "Expression expected, but a namespace name found");
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
                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();
        }

A
Andrey Breslav 已提交
699 700 701
        @Override
        public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
            if (preferBlock && !expression.hasParameterSpecification()) {
702
                trace.recordBlock(expression);
703
                result = getBlockReturnedType(scope, expression.getBody());
A
Andrey Breslav 已提交
704 705 706
                return;
            }

707
            FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.<Annotation>emptyList(), "<anonymous>");
A
Andrey Breslav 已提交
708 709 710 711 712 713 714 715 716 717 718 719

            JetTypeReference returnTypeRef = expression.getReturnTypeRef();

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

            List<JetElement> body = expression.getBody();
720
            final Map<String, VariableDescriptor> parameterDescriptors = new HashMap<String, VariableDescriptor>();
A
Andrey Breslav 已提交
721 722 723 724 725 726
            List<JetType> parameterTypes = new ArrayList<JetType>();
            for (JetParameter parameter : expression.getParameters()) {
                JetTypeReference typeReference = parameter.getTypeReference();
                if (typeReference == null) {
                    throw new UnsupportedOperationException("Type inference for parameters is not implemented yet");
                }
727 728 729
                VariableDescriptor variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(functionDescriptor, scope, parameter);
                parameterDescriptors.put(parameter.getName(), variableDescriptor);
                parameterTypes.add(variableDescriptor.getOutType());
A
Andrey Breslav 已提交
730 731 732 733 734
            }
            JetType returnType;
            if (returnTypeRef != null) {
                returnType = typeResolver.resolveType(scope, returnTypeRef);
            } else {
A
Cleanup  
Andrey Breslav 已提交
735
                WritableScope writableScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler());
736 737
                for (VariableDescriptor variableDescriptor : parameterDescriptors.values()) {
                    writableScope.addVariableDescriptor(variableDescriptor);
A
Andrey Breslav 已提交
738 739
                }
                writableScope.setThisType(receiverType);
740
                returnType = getBlockReturnedType(writableScope, body);
A
Andrey Breslav 已提交
741
            }
742 743
            JetType effectiveReceiverType = receiverTypeRef == null ? null : receiverType;
            JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType;
744
            result = JetStandardClasses.getFunctionType(Collections.<Annotation>emptyList(), effectiveReceiverType, parameterTypes, safeReturnType);
A
Andrey Breslav 已提交
745 746 747 748
        }

        @Override
        public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
749 750 751 752
            JetExpression inner = expression.getExpression();
            if (inner != null) {
                result = getType(scope, inner, false);
            }
A
Andrey Breslav 已提交
753 754 755 756 757 758 759
        }

        @Override
        public void visitConstantExpression(JetConstantExpression expression) {
            IElementType elementType = expression.getNode().getElementType();
            JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
            if (elementType == JetNodeTypes.INTEGER_CONSTANT) {
760 761
                Object value = expression.getValue();
                if (value == null) {
762
                    trace.getErrorHandler().genericError(expression.getNode(), "Number is of range for Long");
763 764
                }
                else if (value instanceof Long) {
A
Andrey Breslav 已提交
765 766 767 768 769 770
                    result = standardLibrary.getLongType();
                }
                else {
                    result = standardLibrary.getIntType();
                }
                // TODO : other ranges
A
Cleanup  
Andrey Breslav 已提交
771 772
            }
            else if (elementType == JetNodeTypes.LONG_CONSTANT) {
A
Andrey Breslav 已提交
773
                result = standardLibrary.getLongType();
A
Cleanup  
Andrey Breslav 已提交
774 775
            }
            else if (elementType == JetNodeTypes.FLOAT_CONSTANT) {
A
Andrey Breslav 已提交
776 777 778 779 780
                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 已提交
781 782
                }
                else {
A
Andrey Breslav 已提交
783 784
                    result = standardLibrary.getDoubleType();
                }
A
Cleanup  
Andrey Breslav 已提交
785 786
            }
            else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) {
A
Andrey Breslav 已提交
787
                result = standardLibrary.getBooleanType();
A
Cleanup  
Andrey Breslav 已提交
788 789
            }
            else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) {
A
Andrey Breslav 已提交
790
                result = standardLibrary.getCharType();
A
Cleanup  
Andrey Breslav 已提交
791 792
            }
            else if (elementType == JetNodeTypes.STRING_CONSTANT) {
A
Andrey Breslav 已提交
793
                result = standardLibrary.getStringType();
A
Cleanup  
Andrey Breslav 已提交
794 795
            }
            else if (elementType == JetNodeTypes.NULL) {
A
Andrey Breslav 已提交
796
                result = JetStandardClasses.getNullableNothingType();
A
Cleanup  
Andrey Breslav 已提交
797 798
            }
            else {
A
Andrey Breslav 已提交
799 800 801 802 803 804
                throw new IllegalArgumentException("Unsupported constant: " + expression);
            }
        }

        @Override
        public void visitThrowExpression(JetThrowExpression expression) {
A
Andrey Breslav 已提交
805 806 807 808 809
            JetExpression thrownExpression = expression.getThrownExpression();
            if (thrownExpression != null) {
                JetType type = getType(scope, thrownExpression, false);
                // TODO : check that it inherits Throwable
            }
A
Andrey Breslav 已提交
810 811 812 813 814 815
            result = JetStandardClasses.getNothingType();
        }

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

A
Andrey Breslav 已提交
817
            if (returnedExpression != null) {
A
Cleanup  
Andrey Breslav 已提交
818
                getType(scope, returnedExpression, false);
A
Andrey Breslav 已提交
819 820
            }

A
Andrey Breslav 已提交
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
            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 已提交
836 837
            JetType type = safeGetType(scope, expression.getBaseExpression(), false);
            result = semanticServices.getStandardLibrary().getTypeInfoType(type);
A
Andrey Breslav 已提交
838 839 840 841
        }

        @Override
        public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) {
A
Andrey Breslav 已提交
842 843 844 845 846 847 848
            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)) {
849
                        trace.getErrorHandler().typeMismatch(expression.getLeft(), targetType, actualType);
A
Andrey Breslav 已提交
850
                    }
A
Andrey Breslav 已提交
851
                    result = targetType;
A
Andrey Breslav 已提交
852
                }
A
Andrey Breslav 已提交
853
                else if (operationType == JetTokens.AS_KEYWORD) {
854
                    checkForCastImpossibility(expression, actualType, targetType);
A
Andrey Breslav 已提交
855 856 857
                    result = targetType;
                }
                else if (operationType == JetTokens.AS_SAFE) {
858
                    checkForCastImpossibility(expression, actualType, targetType);
A
Andrey Breslav 已提交
859
                    result = TypeUtils.makeNullable(targetType);
A
Andrey Breslav 已提交
860 861
                }
                else {
862
                    trace.getErrorHandler().genericError(expression.getOperationSign().getNode(), "Unsupported binary operation");
A
Andrey Breslav 已提交
863
                }
A
Andrey Breslav 已提交
864 865 866
            }
        }

867 868 869 870 871 872
        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)) {
873
                    trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed, use ':' instead");
874 875
                }
                else {
876
                    trace.getErrorHandler().genericError(expression.getOperationSign().getNode(), "This cast can never succeed");
877 878 879 880
                }
            }
            else {
                if (typeChecker.isSubtypeOf(actualType, targetType)) {
881
                    trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed");
882 883 884 885
                }
            }
        }

A
Andrey Breslav 已提交
886 887


A
Andrey Breslav 已提交
888
        @Override
889 890 891 892 893 894 895 896 897
        public void visitTupleExpression(JetTupleExpression expression) {
            List<JetExpression> entries = expression.getEntries();
            List<JetType> types = new ArrayList<JetType>();
            for (JetExpression entry : entries) {
                types.add(getType(scope, entry, false));
            }
            // TODO : labels
            result = JetStandardClasses.getTupleType(types);
        }
A
Andrey Breslav 已提交
898

899 900
        @Override
        public void visitThisExpression(JetThisExpression expression) {
901
            // TODO : qualified this, e.g. this@Foo<Bar>
A
Andrey Breslav 已提交
902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
            JetType thisType = null;
            String labelName = expression.getLabelName();
            if (labelName != null) {
                Collection<DeclarationDescriptor> declarationsByLabel = scope.getDeclarationsByLabel(labelName);
                int size = declarationsByLabel.size();
                if (size == 1) {
                    DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
                    if (declarationDescriptor instanceof ClassDescriptor) {
                        ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
                        thisType = classDescriptor.getDefaultType();
                    }
                    else {
                        throw new UnsupportedOperationException(); // TODO
                    }
                }
                else if (size == 0) {
918
                    trace.getErrorHandler().unresolvedReference(expression.getTargetLabel());
A
Andrey Breslav 已提交
919 920
                }
                else {
921
                    JetSimpleNameExpression labelElement = expression.getTargetLabel();
A
Andrey Breslav 已提交
922
                    assert labelElement != null;
923
                    trace.getErrorHandler().genericError(labelElement.getNode(), "Ambiguous label");
A
Andrey Breslav 已提交
924 925 926 927 928 929 930 931
                }
            }
            else {
                thisType = scope.getThisType();
            }

            if (thisType != null) {
                if (JetStandardClasses.isNothing(thisType)) {
932
                    trace.getErrorHandler().genericError(expression.getNode(), "'this' is not defined in this context");
A
Andrey Breslav 已提交
933 934 935 936 937 938 939 940 941 942 943 944 945 946
                }
                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();
947
                                TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
A
Andrey Breslav 已提交
948 949
                                for (JetType declaredSupertype : supertypes) {
                                    if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
950
                                        result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
A
Andrey Breslav 已提交
951 952 953 954
                                        break;
                                    }
                                }
                                if (result == null) {
955
                                    trace.getErrorHandler().genericError(superTypeElement.getNode(), "Not a superclass");
A
Andrey Breslav 已提交
956
                                }
957 958
                            }
                        }
A
Andrey Breslav 已提交
959 960
                    } else {
                        result = thisType;
961
                    }
A
Andrey Breslav 已提交
962
                }
A
Andrey Breslav 已提交
963 964 965
            }
        }

966 967
        @Override
        public void visitBlockExpression(JetBlockExpression expression) {
968
            result = getBlockReturnedType(scope, expression.getStatements());
969 970
        }

A
Andrey Breslav 已提交
971
        @Override
972
        public void visitWhenExpression(final JetWhenExpression expression) {
A
Andrey Breslav 已提交
973
            // TODO :change scope according to the bound value in the when header
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
            final JetExpression subjectExpression = expression.getSubjectExpression();

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

            // TODO : exhaustive patterns

            for (JetWhenEntry whenEntry : expression.getEntries()) {
                final JetType finalSubjectType = subjectType;
                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) {
                            checkNullSafety(finalSubjectType, condition.getOperationTokenNode());
                            JetExpression callSuffixExpression = condition.getCallSuffixExpression();
                            JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType);
                            if (callSuffixExpression != null) {
                                JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false);
                                ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression");
                            }
                        }

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

                        @Override
                        public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
                            super.visitWhenConditionIsPattern(condition); // TODO
                        }

                        @Override
                        public void visitJetElement(JetElement elem) {
                            trace.getErrorHandler().genericError(elem.getNode(), "Unsupported [JetTypeInferrer] : " + elem);
                        }
                    });
                }
            }

            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 已提交
1041 1042 1043 1044 1045 1046 1047 1048
        }

        @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>();
1049 1050 1051 1052 1053
            for (JetCatchClause catchClause : catchClauses) {
                JetParameter catchParameter = catchClause.getCatchParameter();
                JetExpression catchBody = catchClause.getCatchBody();
                if (catchParameter != null) {
                    VariableDescriptor variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, catchParameter);
1054
                    if (catchBody != null) {
A
Cleanup  
Andrey Breslav 已提交
1055
                        WritableScope catchScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
1056 1057 1058 1059 1060
                        catchScope.addVariableDescriptor(variableDescriptor);
                        JetType type = getType(catchScope, catchBody, true);
                        if (type != null) {
                            types.add(type);
                        }
1061
                    }
A
Andrey Breslav 已提交
1062 1063
                }
            }
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
            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 已提交
1081 1082 1083
        }

        @Override
1084 1085 1086
        public void visitIfExpression(JetIfExpression expression) {
            checkCondition(scope, expression.getCondition());

1087
            // TODO : change types according to is and null checks
1088
            JetExpression elseBranch = expression.getElse();
1089
            JetExpression thenBranch = expression.getThen();
1090 1091 1092 1093 1094 1095

            if (elseBranch == null) {
                if (thenBranch != null) {
                    getType(scope, thenBranch, true);
                    result = JetStandardClasses.getUnitType();
                }
1096
            }
1097 1098 1099 1100 1101 1102
            else if (thenBranch == null) {
                getType(scope, elseBranch, true);
                result = JetStandardClasses.getUnitType();
            }
            else {
                JetType thenType = getType(scope, thenBranch, true);
1103
                JetType elseType = getType(scope, elseBranch, true);
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
                if (thenType == null) {
                    result = elseType;
                }
                else if (elseType == null) {
                    result = thenType;
                }
                else {
                    result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
                }
            }
A
Andrey Breslav 已提交
1114 1115
        }

1116 1117 1118 1119 1120
        private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition) {
            if (condition != null) {
                JetType conditionType = getType(scope, condition, false);

                if (conditionType != null && !isBoolean(conditionType)) {
1121
                    trace.getErrorHandler().genericError(condition.getNode(), "Condition must be of type Boolean, but was of type " + conditionType);
A
Andrey Breslav 已提交
1122 1123 1124 1125 1126
                }
            }
        }

        @Override
1127 1128 1129 1130 1131 1132 1133
        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 已提交
1134 1135 1136
        }

        @Override
1137 1138
        public void visitDoWhileExpression(JetDoWhileExpression expression) {
            JetExpression body = expression.getBody();
A
Andrey Breslav 已提交
1139 1140 1141 1142
            JetScope conditionScope = scope;
            if (body instanceof JetFunctionLiteralExpression) {
                JetFunctionLiteralExpression function = (JetFunctionLiteralExpression) body;
                if (!function.hasParameterSpecification()) {
A
Cleanup  
Andrey Breslav 已提交
1143
                    WritableScope writableScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
A
Andrey Breslav 已提交
1144
                    conditionScope = writableScope;
1145
                    getBlockReturnedTypeWithWritableScope(writableScope, function.getBody());
A
Andrey Breslav 已提交
1146
                    trace.recordBlock(function);
A
Andrey Breslav 已提交
1147 1148 1149 1150 1151
                } else {
                    getType(scope, body, true);
                }
            }
            else if (body != null) {
A
Cleanup  
Andrey Breslav 已提交
1152
                WritableScope writableScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
A
Andrey Breslav 已提交
1153
                conditionScope = writableScope;
1154
                getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body));
1155 1156 1157 1158 1159 1160 1161 1162 1163
            }
            checkCondition(conditionScope, expression.getCondition());
            result = JetStandardClasses.getUnitType();
        }

        @Override
        public void visitForExpression(JetForExpression expression) {
            JetParameter loopParameter = expression.getLoopParameter();
            JetExpression loopRange = expression.getLoopRange();
1164 1165 1166 1167
            JetType loopRangeType = null;
            if (loopRange != null) {
                loopRangeType = getType(scope, loopRange, false);
            }
1168 1169
            JetType expectedParameterType = null;
            if (loopRangeType != null) {
1170 1171 1172
                expectedParameterType = checkIterableConvention(loopRangeType, loopRange.getNode());
            }

A
Cleanup  
Andrey Breslav 已提交
1173
            WritableScope loopScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
1174 1175 1176

            if (loopParameter != null) {
                JetTypeReference typeReference = loopParameter.getTypeReference();
1177
                VariableDescriptor variableDescriptor;
1178
                if (typeReference != null) {
1179 1180
                    variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, loopParameter);
                    JetType actualParameterType = variableDescriptor.getOutType();
1181 1182 1183
                    if (expectedParameterType != null &&
                            actualParameterType != null &&
                            !semanticServices.getTypeChecker().isSubtypeOf(expectedParameterType, actualParameterType)) {
1184
                        trace.getErrorHandler().genericError(typeReference.getNode(), "The loop iterates over values of type " + expectedParameterType + " but the parameter is declared to be " + actualParameterType);
1185
                    }
1186 1187
                }
                else {
1188 1189
                    if (expectedParameterType == null) {
                        expectedParameterType = ErrorUtils.createErrorType("Error");
1190
                    }
1191
                    variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), loopParameter, expectedParameterType);
1192
                }
1193
                loopScope.addVariableDescriptor(variableDescriptor);
1194 1195
            }

1196 1197 1198 1199
            JetExpression body = expression.getBody();
            if (body != null) {
                getType(loopScope, body, true); // TODO
            }
1200

1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
            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);
1211
                if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) {
1212
                    // TODO : overload resolution rules impose priorities here???
1213
                    trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext()' property");
1214 1215
                }
                else if (!hasNextFunctionSupported && !hasNextPropertySupported) {
1216
                    trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
1217 1218 1219 1220
                }

                OverloadResolutionResult nextResolutionResult = resolveNoParametersFunction(iteratorType, scope, "next");
                if (nextResolutionResult.isAmbiguity()) {
1221
                    trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression");
1222
                } else if (nextResolutionResult.isNothing()) {
1223
                    trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().next()' method");
1224 1225
                } else {
                    return nextResolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
1226 1227 1228
                }
            }
            else {
1229 1230 1231
                String errorMessage = "For-loop range must have an iterator() method";
                if (iteratorResolutionResult.isAmbiguity()) {
                    errorMessage = "Method 'iterator()' is ambiguous for this expression";
1232
                }
1233
                trace.getErrorHandler().genericError(reportErrorsOn, errorMessage);
1234
            }
1235 1236
            return null;
        }
1237

1238 1239 1240
        private boolean checkHasNextFunctionSupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) {
            OverloadResolutionResult hasNextResolutionResult = resolveNoParametersFunction(iteratorType, scope, "hasNext");
            if (hasNextResolutionResult.isAmbiguity()) {
1241
                trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().hasNext()' is ambiguous for this expression");
1242 1243 1244 1245 1246
            } else if (hasNextResolutionResult.isNothing()) {
                return false;
            } else {
                JetType hasNextReturnType = hasNextResolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
                if (!isBoolean(hasNextReturnType)) {
1247
                    trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext()' method of the loop range must return Boolean, but returns " + hasNextReturnType);
1248
                }
1249
            }
1250 1251
            return true;
        }
1252

1253
        private boolean checkHasNextPropertySupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) {
1254
            VariableDescriptor hasNextProperty = iteratorType.getMemberScope().getVariable("hasNext");
1255 1256 1257 1258 1259 1260 1261
            // TODO :extension properties
            if (hasNextProperty == null) {
                return false;
            } else {
                JetType hasNextReturnType = hasNextProperty.getOutType();
                if (hasNextReturnType == null) {
                    // TODO : accessibility
1262
                    trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must be readable");
1263 1264
                }
                else if (!isBoolean(hasNextReturnType)) {
1265
                    trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must return Boolean, but returns " + hasNextReturnType);
1266 1267 1268 1269 1270 1271 1272 1273 1274
                }
            }
            return true;
        }

        @NotNull
        private OverloadResolutionResult resolveNoParametersFunction(@NotNull JetType receiverType, @NotNull JetScope scope, @NotNull String name) {
            OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name);
            return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<JetType>emptyList(), Collections.<JetType>emptyList());
A
Andrey Breslav 已提交
1275 1276 1277 1278 1279 1280
        }

        @Override
        public void visitNewExpression(JetNewExpression expression) {
            // TODO : type argument inference
            JetTypeReference typeReference = expression.getTypeReference();
1281
            if (typeReference != null) {
1282
                result = checkConstructorCall(scope, typeReference, expression);
1283
            }
A
Andrey Breslav 已提交
1284 1285 1286
        }

        @Override
A
Andrey Breslav 已提交
1287
        public void visitHashQualifiedExpression(JetHashQualifiedExpression expression) {
1288
            trace.getErrorHandler().genericError(expression.getOperationTokenNode(), "Unsupported");
A
Andrey Breslav 已提交
1289 1290 1291 1292
        }

        @Override
        public void visitQualifiedExpression(JetQualifiedExpression expression) {
A
Andrey Breslav 已提交
1293 1294
            // TODO : functions
            JetExpression selectorExpression = expression.getSelectorExpression();
1295
            JetExpression receiverExpression = expression.getReceiverExpression();
1296
            JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression);
A
Andrey Breslav 已提交
1297
            if (receiverType != null) {
1298
                checkNullSafety(receiverType, expression.getOperationTokenNode());
A
Andrey Breslav 已提交
1299 1300
                JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
                if (expression.getOperationSign() == JetTokens.QUEST) {
1301
                    if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) {
A
Andrey Breslav 已提交
1302
                        // TODO : more comprehensible error message
1303
                        trace.getErrorHandler().typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType);
A
Andrey Breslav 已提交
1304 1305
                    }
                    result = TypeUtils.makeNullable(receiverType);
A
Andrey Breslav 已提交
1306
                }
A
Andrey Breslav 已提交
1307 1308
                else {
                    result = selectorReturnType;
1309
                }
1310 1311 1312
                if (selectorExpression != null && result != null) {
                    trace.recordExpressionType(selectorExpression, result);
                }
A
Andrey Breslav 已提交
1313 1314 1315
            }
        }

A
Andrey Breslav 已提交
1316 1317 1318 1319
        private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) {
            JetScope compositeScope = new ScopeWithReceiver(scope, receiverType);
            if (selectorExpression instanceof JetCallExpression) {
                JetCallExpression callExpression = (JetCallExpression) selectorExpression;
1320
                OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
A
Andrey Breslav 已提交
1321 1322 1323 1324 1325 1326 1327
                return resolveOverloads(scope, callExpression, overloadDomain);
            }
            else if (selectorExpression instanceof JetSimpleNameExpression) {
                return getType(compositeScope, selectorExpression, false);
            }
            else if (selectorExpression != null) {
                // TODO : not a simple name -> resolve in scope, expect property type or a function type
1328
                trace.getErrorHandler().genericError(selectorExpression.getNode(), "Unsupported selector element type: " + selectorExpression);
A
Andrey Breslav 已提交
1329 1330 1331 1332
            }
            return receiverType;
        }

A
Andrey Breslav 已提交
1333 1334 1335
        @Override
        public void visitCallExpression(JetCallExpression expression) {
            JetExpression calleeExpression = expression.getCalleeExpression();
1336
            OverloadDomain overloadDomain = getOverloadDomain(scope, calleeExpression, expression.getValueArgumentList());
A
Andrey Breslav 已提交
1337
            result = resolveOverloads(scope, expression, overloadDomain);
1338
        }
A
Andrey Breslav 已提交
1339

A
Andrey Breslav 已提交
1340 1341 1342
        @Override
        public void visitIsExpression(JetIsExpression expression) {
            // TODO : patterns and everything
A
Andrey Breslav 已提交
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
            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?
                    }
                }

            }
A
Andrey Breslav 已提交
1356 1357 1358
            result = semanticServices.getStandardLibrary().getBooleanType();
        }

A
Andrey Breslav 已提交
1359
        @Override
1360
        public void visitUnaryExpression(JetUnaryExpression expression) {
A
Andrey Breslav 已提交
1361
            JetSimpleNameExpression operationSign = expression.getOperationSign();
1362 1363 1364 1365 1366
            if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
                // TODO : Some processing for the label?
                result = getType(expression.getBaseExpression());
                return;
            }
A
Andrey Breslav 已提交
1367 1368
            IElementType operationType = operationSign.getReferencedNameElementType();
            String name = unaryOperationNames.get(operationType);
1369
            if (name == null) {
1370
                trace.getErrorHandler().genericError(operationSign.getNode(), "Unknown unary operation");
1371 1372
            }
            else {
A
Andrey Breslav 已提交
1373 1374 1375
                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 已提交
1376
                    if (functionDescriptor != null) {
A
Andrey Breslav 已提交
1377 1378
                        JetType returnType = functionDescriptor.getUnsubstitutedReturnType();
                        if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
1379 1380 1381 1382 1383
                            if (semanticServices.getTypeChecker().isSubtypeOf(returnType, JetStandardClasses.getUnitType())) {
                                 result = JetStandardClasses.getUnitType();
                            }
                            else {
                                if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) {
1384
                                    trace.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType);
1385 1386 1387
                                }
                                // TODO : Maybe returnType?
                                result = receiverType;
A
Andrey Breslav 已提交
1388 1389 1390 1391
                            }
                        } else {
                            result = returnType;
                        }
A
Andrey Breslav 已提交
1392 1393 1394 1395 1396 1397 1398 1399 1400
                    }
                }
            }
        }

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

A
Andrey Breslav 已提交
1401 1402 1403
            JetExpression left = expression.getLeft();
            JetExpression right = expression.getRight();

A
Andrey Breslav 已提交
1404 1405
            IElementType operationType = operationSign.getReferencedNameElementType();
            if (operationType == JetTokens.IDENTIFIER) {
1406 1407 1408 1409
                String referencedName = operationSign.getReferencedName();
                if (referencedName != null) {
                    result = getTypeForBinaryCall(expression, referencedName, scope, true);
                }
A
Andrey Breslav 已提交
1410
            }
1411
            else if (binaryOperationNames.containsKey(operationType)) {
A
Andrey Breslav 已提交
1412
                result = getTypeForBinaryCall(expression, binaryOperationNames.get(operationType), scope, true);
A
Andrey Breslav 已提交
1413 1414
            }
            else if (operationType == JetTokens.EQ) {
A
Andrey Breslav 已提交
1415 1416 1417 1418
                visitAssignment(expression);
            }
            else if (assignmentOperationNames.containsKey(operationType)) {
                visitAssignmentOperation(expression);
A
Andrey Breslav 已提交
1419
            }
1420
            else if (comparisonOperations.contains(operationType)) {
A
Andrey Breslav 已提交
1421
                JetType compareToReturnType = getTypeForBinaryCall(expression, "compareTo", scope, true);
A
Andrey Breslav 已提交
1422 1423 1424 1425 1426 1427 1428
                if (compareToReturnType != null) {
                    TypeConstructor constructor = compareToReturnType.getConstructor();
                    JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
                    TypeConstructor intTypeConstructor = standardLibrary.getInt().getTypeConstructor();
                    if (constructor.equals(intTypeConstructor)) {
                        result = standardLibrary.getBooleanType();
                    } else {
1429
                        trace.getErrorHandler().genericError(operationSign.getNode(), "compareTo must return Int, but returns " + compareToReturnType);
A
Andrey Breslav 已提交
1430
                    }
A
Andrey Breslav 已提交
1431
                }
A
Andrey Breslav 已提交
1432
            }
A
Equals  
Andrey Breslav 已提交
1433
            else if (equalsOperations.contains(operationType)) {
A
Andrey Breslav 已提交
1434
                String name = "equals";
1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
                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 {
1449
                                trace.getErrorHandler().genericError(operationSign.getNode(), "No method 'equals(Any?) : Boolean' available");
1450 1451 1452 1453 1454
                            }
                        }
                    }
                }
                result = semanticServices.getStandardLibrary().getBooleanType();
1455 1456 1457 1458 1459 1460
            }
            else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
                ensureNonemptyIntersectionOfOperandTypes(expression);

                // TODO : Check comparison pointlessness
                result = semanticServices.getStandardLibrary().getBooleanType();
A
Andrey Breslav 已提交
1461 1462 1463
            }
            else if (inOperations.contains(operationType)) {
                if (right == null) {
A
rename  
Andrey Breslav 已提交
1464
                    result = ErrorUtils.createErrorType("No right argument"); // TODO
A
Andrey Breslav 已提交
1465
                    return;
A
Andrey Breslav 已提交
1466
                }
1467
                checkInExpression(operationSign, left, right);
1468
                result = semanticServices.getStandardLibrary().getBooleanType();
A
Equals  
Andrey Breslav 已提交
1469
            }
A
Andrey Breslav 已提交
1470 1471 1472 1473
            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)) {
1474
                    trace.getErrorHandler().typeMismatch(left, semanticServices.getStandardLibrary().getBooleanType(), leftType);
A
Andrey Breslav 已提交
1475 1476
                }
                if (rightType != null && !isBoolean(rightType)) {
1477
                    trace.getErrorHandler().typeMismatch(right, semanticServices.getStandardLibrary().getBooleanType(), rightType);
A
Andrey Breslav 已提交
1478 1479 1480
                }
                result = semanticServices.getStandardLibrary().getBooleanType();
            }
A
Andrey Breslav 已提交
1481 1482 1483 1484 1485
            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()) {
1486
                        trace.getErrorHandler().genericWarning(left.getNode(), "Elvis operator (?:) is always returns the left operand of non-nullable type " + leftType);
A
Andrey Breslav 已提交
1487 1488 1489 1490 1491 1492
                    }
                    if (rightType != null) {
                        result = TypeUtils.makeNullableAsSpecified(semanticServices.getTypeChecker().commonSupertype(leftType, rightType), rightType.isNullable());
                    }
                }
            }
A
Equals  
Andrey Breslav 已提交
1493
            else {
1494
                trace.getErrorHandler().genericError(operationSign.getNode(), "Unknown operation");
A
Andrey Breslav 已提交
1495 1496 1497
            }
        }

1498 1499 1500 1501 1502 1503
        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);
        }

1504 1505 1506 1507 1508 1509 1510
        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);
1511
            if (leftType != null && right != null) {
1512 1513
                JetType rightType = getType(scope, right, false);

1514 1515 1516
                if (rightType != null) {
                    JetType intersect = TypeUtils.intersect(semanticServices.getTypeChecker(), new HashSet<JetType>(Arrays.asList(leftType, rightType)));
                    if (intersect == null) {
1517
                        trace.getErrorHandler().genericError(expression.getNode(), "Operator " + operationSign.getReferencedName() + " cannot be applied to " + leftType + " and " + rightType);
1518
                    }
1519 1520 1521 1522
                }
            }
        }

A
Andrey Breslav 已提交
1523 1524 1525 1526 1527 1528 1529 1530 1531
        protected void visitAssignmentOperation(JetBinaryExpression expression) {
            assignmentIsNotAnExpressionError(expression);
        }

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

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

1535 1536 1537 1538 1539
        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 已提交
1540 1541
            if (resultType != null) {
                // TODO : Relax?
A
Andrey Breslav 已提交
1542
                if (!isBoolean(resultType)) {
1543
                    trace.getErrorHandler().genericError(operationSign.getNode(), subjectName + " must return Boolean but returns " + resultType);
1544
                    return false;
A
Andrey Breslav 已提交
1545 1546
                }
            }
1547
            return true;
A
Andrey Breslav 已提交
1548 1549
        }

A
Andrey Breslav 已提交
1550
        private boolean isBoolean(@NotNull JetType type) {
A
Andrey Breslav 已提交
1551
            return semanticServices.getTypeChecker().isConvertibleTo(type,  semanticServices.getStandardLibrary().getBooleanType());
A
Andrey Breslav 已提交
1552 1553
        }

A
Andrey Breslav 已提交
1554 1555 1556 1557 1558 1559 1560 1561
        @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;

1562 1563 1564 1565 1566
            if (receiverType != null) {
                FunctionDescriptor functionDescriptor = lookupFunction(scope, expression, "get", receiverType, argumentTypes, true);
                if (functionDescriptor != null) {
                    result = functionDescriptor.getUnsubstitutedReturnType();
                }
A
Andrey Breslav 已提交
1567 1568 1569
            }
        }

1570
        @Nullable
1571 1572 1573 1574 1575
        protected JetType getTypeForBinaryCall(
                @NotNull JetBinaryExpression expression,
                @NotNull String name,
                @NotNull JetScope scope,
                boolean reportUnresolved) {
A
Andrey Breslav 已提交
1576 1577 1578
            JetExpression left = expression.getLeft();
            JetExpression right = expression.getRight();
            if (right == null) {
1579
                return null;
A
Andrey Breslav 已提交
1580
            }
A
Andrey Breslav 已提交
1581 1582 1583 1584
            JetSimpleNameExpression operationSign = expression.getOperationReference();
            return getTypeForBinaryCall(scope, left, operationSign, right, name, reportUnresolved);
        }

1585
        @Nullable
1586 1587 1588 1589 1590 1591 1592 1593 1594 1595
        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) {
1596 1597
                return null;
            }
A
Andrey Breslav 已提交
1598
            FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType), reportUnresolved);
A
Andrey Breslav 已提交
1599
            if (functionDescriptor != null) {
1600 1601
                if (leftType.isNullable()) {
                    // TODO : better error message for '1 + nullableVar' case
1602
                    trace.getErrorHandler().genericError(operationSign.getNode(),
1603 1604 1605 1606 1607 1608
                            "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 已提交
1609 1610 1611 1612
                return functionDescriptor.getUnsubstitutedReturnType();
            }
            return null;
        }
A
Andrey Breslav 已提交
1613 1614 1615

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

1619 1620
        @Override
        public void visitRootNamespaceExpression(JetRootNamespaceExpression expression) {
1621
            trace.getErrorHandler().genericError(expression.getNode(), "'namespace' is not an expression");
1622 1623 1624
            result = null;
        }

A
Andrey Breslav 已提交
1625 1626
        @Override
        public void visitJetElement(JetElement elem) {
1627
            trace.getErrorHandler().genericError(elem.getNode(), "[JetTypeInferrer] Unsupported element: " + elem + " " + elem.getClass().getCanonicalName());
A
Andrey Breslav 已提交
1628 1629 1630
        }
    }

1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654
    private class TypeInferrerVisitorWithNamespaces extends TypeInferrerVisitor {
        private TypeInferrerVisitorWithNamespaces(@NotNull JetScope scope, boolean preferBlock) {
            super(scope, preferBlock);
        }

        @NotNull
        @Override
        public TypeInferrerVisitor createNew(JetScope scope, boolean preferBlock) {
            return new TypeInferrerVisitorWithNamespaces(scope, preferBlock);
        }

        @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 已提交
1655 1656 1657
    private class TypeInferrerVisitorWithWritableScope extends TypeInferrerVisitor {
        private final WritableScope scope;

1658 1659
        public TypeInferrerVisitorWithWritableScope(@NotNull WritableScope scope, boolean preferBlock) {
            super(scope, preferBlock);
A
Andrey Breslav 已提交
1660 1661 1662 1663 1664
            this.scope = scope;
        }

        @Override
        public void visitProperty(JetProperty property) {
1665 1666 1667

            JetPropertyAccessor getter = property.getGetter();
            if (getter != null) {
1668
                trace.getErrorHandler().genericError(getter.getNode(), "Local variables are not allowed to have getters");
1669 1670 1671 1672
            }

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

1676
            VariableDescriptor propertyDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, property);
1677 1678 1679 1680 1681 1682 1683
            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)) {
1684
                    trace.getErrorHandler().typeMismatch(initializer, outType, initializerType);
1685 1686 1687
                }
            }

1688
            scope.addVariableDescriptor(propertyDescriptor);
A
Andrey Breslav 已提交
1689 1690 1691 1692
        }

        @Override
        public void visitFunction(JetFunction function) {
1693
            scope.addFunctionDescriptor(classDescriptorResolver.resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function));
A
Andrey Breslav 已提交
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725
        }

        @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);
            }
1726
            result = null; // not an expression
A
Andrey Breslav 已提交
1727 1728 1729 1730 1731
        }

        @Override
        protected void visitAssignment(JetBinaryExpression expression) {
            JetExpression left = expression.getLeft();
1732
            JetExpression deparenthesized = JetPsiUtil.deparenthesize(left);
A
Andrey Breslav 已提交
1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
            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)) {
1745
                        trace.getErrorHandler().typeMismatch(right, leftType, rightType);
A
Andrey Breslav 已提交
1746 1747 1748
                    }
                }
            }
A
Andrey Breslav 已提交
1749
            result = null; // This is not an element
A
Andrey Breslav 已提交
1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771
        }

        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
        public void visitJetElement(JetElement elem) {
1772
            trace.getErrorHandler().genericError(elem.getNode(), "Unsupported element in a block: " + elem + " " + elem.getClass().getCanonicalName());
A
Andrey Breslav 已提交
1773
        }
A
Andrey Breslav 已提交
1774
    }
A
Andrey Breslav 已提交
1775

1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787
//    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);
//        }
//    }
1788
}