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

D
Dmitry Jemerov 已提交
3
import com.google.common.collect.ImmutableMap;
4
import com.intellij.lang.ASTNode;
5
import com.intellij.psi.PsiElement;
6 7 8 9 10
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;
11
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
12 13 14
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lexer.JetTokens;
15
import org.jetbrains.jet.resolve.DescriptorUtil;
16 17 18 19 20 21 22 23

import java.util.*;

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

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

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

65 66
    private final Map<JetExpression, JetType> typeCache = new HashMap<JetExpression, JetType>();

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

73 74
    public JetTypeInferrer(@NotNull BindingTrace trace, @NotNull JetFlowInformationProvider flowInformationProvider, @NotNull JetSemanticServices semanticServices) {
        this.trace = new CachedBindingTrace(trace);
75
        this.semanticServices = semanticServices;
A
Andrey Breslav 已提交
76
        this.typeResolver = new TypeResolver(trace, semanticServices);
77
        this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
78
        this.flowInformationProvider = flowInformationProvider;
79 80
    }

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

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

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

110 111 112 113 114 115 116 117 118 119
    @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);
120 121
        OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<JetType>emptyList(), argumentTypes);
        return resolutionResult.isSuccess() ? resolutionResult.getFunctionDescriptor() : null;
122 123 124 125 126 127 128
    }

    private OverloadDomain getOverloadDomain(
            @NotNull final JetScope scope,
            @NotNull JetExpression calleeExpression,
            @Nullable PsiElement argumentList
    ) {
129
        final OverloadDomain[] result = new OverloadDomain[1];
130
        final JetSimpleNameExpression[] reference = new JetSimpleNameExpression[1];
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
        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 已提交
148 149 150
                JetType receiverType = getType(scope, expression.getReceiverExpression(), false);
                checkNullSafety(receiverType, expression);

151
                JetExpression selectorExpression = expression.getSelectorExpression();
152 153
                if (selectorExpression instanceof JetSimpleNameExpression) {
                    JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression;
154
                    String referencedName = referenceExpression.getReferencedName();
155

156 157
                    if (receiverType != null && referencedName != null) {
                        result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
158 159
                        reference[0] = referenceExpression;
                    }
160 161 162 163 164 165
                } else {
                    throw new UnsupportedOperationException(); // TODO
                }
            }

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

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

            @Override
            public void visitJetElement(JetElement elem) {
A
Andrey Breslav 已提交
183
                semanticServices.getErrorHandler().genericError(elem.getNode(), "Unsupported in call element"); // TODO : Message
184 185
            }
        });
186
        return wrapForTracing(result[0], reference[0], argumentList, true);
187 188
    }

A
Andrey Breslav 已提交
189 190
    private void checkNullSafety(JetType receiverType, JetQualifiedExpression expression) {
        if (receiverType != null) {
191 192 193
            boolean namespaceType = receiverType instanceof NamespaceType;
            boolean nullable = !namespaceType && receiverType.isNullable();
            if (nullable && expression.getOperationSign() == JetTokens.DOT) {
A
Andrey Breslav 已提交
194 195
                semanticServices.getErrorHandler().genericError(expression.getOperationTokenNode(), "Only safe calls (?.) are allowed on a nullable receiver of type " + receiverType);
            }
196 197 198 199 200 201 202
            else if (!nullable && expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
                if (namespaceType) {
                    semanticServices.getErrorHandler().genericError(expression.getOperationTokenNode(), "Safe calls are not allowed on namespaces");
                }
                else {
                    semanticServices.getErrorHandler().genericWarning(expression.getOperationTokenNode(), "Unnecessary safe call on a non-null receiver of type  " + receiverType);
                }
A
Andrey Breslav 已提交
203 204 205 206
            }
        }
    }

207 208
    private OverloadDomain wrapForTracing(
            @Nullable final OverloadDomain overloadDomain,
209
            final JetReferenceExpression referenceExpression,
210
            @Nullable final PsiElement argumentList,
211
            final boolean reportErrors) {
212
        if (overloadDomain == null) return OverloadDomain.EMPTY;
213
        assert referenceExpression != null;
214
        return new OverloadDomain() {
215
            @NotNull
216
            @Override
217 218 219 220
            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;
221 222
            }

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

            @Override
            public boolean isEmpty() {
                return overloadDomain.isEmpty();
267 268 269 270
            }
        };
    }

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

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

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

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

340
    @Nullable
341
    private JetType getBlockReturnedType(@NotNull JetScope outerScope, @NotNull List<JetElement> block) {
342 343
        if (block.isEmpty()) {
            return JetStandardClasses.getUnitType();
A
Andrey Breslav 已提交
344
        }
A
Andrey Breslav 已提交
345 346 347

        DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration();
        WritableScope scope = semanticServices.createWritableScope(outerScope, containingDescriptor);
348
        return getBlockReturnedTypeWithWritableScope(scope, block);
A
Andrey Breslav 已提交
349 350
    }

351
    private JetType getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List<? extends JetElement> block) {
352 353 354
        if (block.isEmpty()) {
            return JetStandardClasses.getUnitType();
        }
A
Andrey Breslav 已提交
355

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

A
Andrey Breslav 已提交
358 359
        JetType result = null;
        for (JetElement statement : block) {
360 361 362
            trace.recordStatement(statement);
            JetExpression statementExpression = (JetExpression) statement;
            result = blockLevelVisitor.getType(statementExpression);
A
Andrey Breslav 已提交
363
            blockLevelVisitor.resetResult(); // TODO : maybe it's better to recreate the visitors with the same scope?
364
        }
A
Andrey Breslav 已提交
365
        return result;
366 367
    }

A
Andrey Breslav 已提交
368
    private void collectAllReturnTypes(JetWhenExpression whenExpression, JetScope scope, List<JetType> result) {
369 370 371 372 373 374 375 376 377 378 379 380 381
        for (JetWhenEntry entry : whenExpression.getEntries()) {
            JetWhenExpression subWhen = entry.getSubWhen();
            if (subWhen != null) {
                collectAllReturnTypes(subWhen, scope, result);
            } else {
                JetExpression resultExpression = entry.getExpression();
                if (resultExpression != null) {
                    result.add(getType(scope, resultExpression, true));
                }
            }
        }
    }

A
Andrey Breslav 已提交
382 383 384
    private class TypeInferrerVisitor extends JetVisitor {
        private final JetScope scope;
        private final boolean preferBlock;
A
Andrey Breslav 已提交
385

386
        protected JetType result;
A
Andrey Breslav 已提交
387

388
        private TypeInferrerVisitor(@NotNull JetScope scope, boolean preferBlock) {
A
Andrey Breslav 已提交
389 390 391 392
            this.scope = scope;
            this.preferBlock = preferBlock;
        }

393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
        @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 {
                visitor = new TypeInferrerVisitor(scope, preferBlock);
            }
            JetType type = visitor.getType(expression);
            visitor.result = null;
            return type;
        }

        @Nullable
        public JetType getType(@NotNull JetExpression expression) {
            assert result == null;
            expression.accept(this);
            if (result != null) {
                trace.recordExpressionType(expression, result);
413
                if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
414 415
                    markDominatedExpressionsAsUnreachable(expression);
                }
416
            }
417

A
Andrey Breslav 已提交
418 419 420
            return result;
        }

421 422 423 424
        public void resetResult() {
            result = null;
        }

425 426 427 428 429 430 431 432 433 434 435 436
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

A
Andrey Breslav 已提交
437 438
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

A
Andrey Breslav 已提交
439
        @Override
440
        public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
A
Andrey Breslav 已提交
441 442
            // TODO : other members
            // TODO : type substitutions???
A
Andrey Breslav 已提交
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
            if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
                PropertyDescriptor property = scope.getPropertyByFieldReference(expression.getReferencedName());
                if (property == null) {
                    semanticServices.getErrorHandler().unresolvedReference(expression);
                }
                else {
                    trace.recordReferenceResolution(expression, property);
                    result = property.getOutType();
                }
            }
            else {
                assert  expression.getReferencedNameElementType() == JetTokens.IDENTIFIER;
                String referencedName = expression.getReferencedName();
                if (referencedName != null) {
                    VariableDescriptor variable = scope.getVariable(referencedName);
                    if (variable != null) {
                        trace.recordReferenceResolution(expression, variable);
                        result = variable.getOutType();
                        if (result == null) {
                            semanticServices.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context");
                        }
464
                        return;
A
Andrey Breslav 已提交
465 466 467 468 469 470 471
                    } else {
                        NamespaceDescriptor namespace = scope.getNamespace(referencedName);
                        if (namespace != null) {
                            trace.recordReferenceResolution(expression, namespace);
                            result = namespace.getNamespaceType();
                            return;
                        }
472
                    }
A
Andrey Breslav 已提交
473
                    semanticServices.getErrorHandler().unresolvedReference(expression);
A
Andrey Breslav 已提交
474 475 476 477 478 479 480
                }
            }
        }

        @Override
        public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
            if (preferBlock && !expression.hasParameterSpecification()) {
481
                trace.recordBlock(expression);
482
                result = getBlockReturnedType(scope, expression.getBody());
A
Andrey Breslav 已提交
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
                return;
            }

            FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.<Attribute>emptyList(), "<anonymous>");

            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();
499
            final Map<String, VariableDescriptor> parameterDescriptors = new HashMap<String, VariableDescriptor>();
A
Andrey Breslav 已提交
500 501 502 503 504 505
            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");
                }
506 507 508
                VariableDescriptor variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(functionDescriptor, scope, parameter);
                parameterDescriptors.put(parameter.getName(), variableDescriptor);
                parameterTypes.add(variableDescriptor.getOutType());
A
Andrey Breslav 已提交
509 510 511 512 513
            }
            JetType returnType;
            if (returnTypeRef != null) {
                returnType = typeResolver.resolveType(scope, returnTypeRef);
            } else {
514
                WritableScope writableScope = semanticServices.createWritableScope(scope, functionDescriptor);
515 516
                for (VariableDescriptor variableDescriptor : parameterDescriptors.values()) {
                    writableScope.addVariableDescriptor(variableDescriptor);
A
Andrey Breslav 已提交
517 518
                }
                writableScope.setThisType(receiverType);
519
                returnType = getBlockReturnedType(writableScope, body);
A
Andrey Breslav 已提交
520
            }
521 522
            JetType effectiveReceiverType = receiverTypeRef == null ? null : receiverType;
            JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType;
523
            result = JetStandardClasses.getFunctionType(Collections.<Attribute>emptyList(), effectiveReceiverType, parameterTypes, safeReturnType);
A
Andrey Breslav 已提交
524 525 526 527
        }

        @Override
        public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
528 529 530 531
            JetExpression inner = expression.getExpression();
            if (inner != null) {
                result = getType(scope, inner, false);
            }
A
Andrey Breslav 已提交
532 533 534 535 536 537 538
        }

        @Override
        public void visitConstantExpression(JetConstantExpression expression) {
            IElementType elementType = expression.getNode().getElementType();
            JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
            if (elementType == JetNodeTypes.INTEGER_CONSTANT) {
539 540 541 542 543
                Object value = expression.getValue();
                if (value == null) {
                    semanticServices.getErrorHandler().genericError(expression.getNode(), "Number is of range for Long");
                }
                else if (value instanceof Long) {
A
Andrey Breslav 已提交
544 545 546 547 548 549
                    result = standardLibrary.getLongType();
                }
                else {
                    result = standardLibrary.getIntType();
                }
                // TODO : other ranges
A
Cleanup  
Andrey Breslav 已提交
550 551
            }
            else if (elementType == JetNodeTypes.LONG_CONSTANT) {
A
Andrey Breslav 已提交
552
                result = standardLibrary.getLongType();
A
Cleanup  
Andrey Breslav 已提交
553 554
            }
            else if (elementType == JetNodeTypes.FLOAT_CONSTANT) {
A
Andrey Breslav 已提交
555 556 557 558 559
                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 已提交
560 561
                }
                else {
A
Andrey Breslav 已提交
562 563
                    result = standardLibrary.getDoubleType();
                }
A
Cleanup  
Andrey Breslav 已提交
564 565
            }
            else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) {
A
Andrey Breslav 已提交
566
                result = standardLibrary.getBooleanType();
A
Cleanup  
Andrey Breslav 已提交
567 568
            }
            else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) {
A
Andrey Breslav 已提交
569
                result = standardLibrary.getCharType();
A
Cleanup  
Andrey Breslav 已提交
570 571
            }
            else if (elementType == JetNodeTypes.STRING_CONSTANT) {
A
Andrey Breslav 已提交
572
                result = standardLibrary.getStringType();
A
Cleanup  
Andrey Breslav 已提交
573 574
            }
            else if (elementType == JetNodeTypes.NULL) {
A
Andrey Breslav 已提交
575
                result = JetStandardClasses.getNullableNothingType();
A
Cleanup  
Andrey Breslav 已提交
576 577
            }
            else {
A
Andrey Breslav 已提交
578 579 580 581 582 583 584 585 586 587 588 589
                throw new IllegalArgumentException("Unsupported constant: " + expression);
            }
        }

        @Override
        public void visitThrowExpression(JetThrowExpression expression) {
            result = JetStandardClasses.getNothingType();
        }

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

A
Andrey Breslav 已提交
591
            if (returnedExpression != null) {
A
Cleanup  
Andrey Breslav 已提交
592
                getType(scope, returnedExpression, false);
A
Andrey Breslav 已提交
593 594
            }

A
Andrey Breslav 已提交
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
            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 已提交
610
            semanticServices.getErrorHandler().genericError(expression.getNode(), "Return some reflection interface"); // TODO
A
Andrey Breslav 已提交
611 612 613 614
        }

        @Override
        public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) {
A
Andrey Breslav 已提交
615 616 617 618 619 620 621 622 623
            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)) {
                        semanticServices.getErrorHandler().typeMismatch(expression.getLeft(), targetType, actualType);
                    }
A
Andrey Breslav 已提交
624
                    result = targetType;
A
Andrey Breslav 已提交
625
                }
A
Andrey Breslav 已提交
626
                else if (operationType == JetTokens.AS_KEYWORD) {
627
                    checkForCastImpossibility(expression, actualType, targetType);
A
Andrey Breslav 已提交
628 629 630
                    result = targetType;
                }
                else if (operationType == JetTokens.AS_SAFE) {
631
                    checkForCastImpossibility(expression, actualType, targetType);
A
Andrey Breslav 已提交
632
                    result = TypeUtils.makeNullable(targetType);
A
Andrey Breslav 已提交
633 634
                }
                else {
A
Andrey Breslav 已提交
635
                    semanticServices.getErrorHandler().genericError(expression.getOperationSign().getNode(), "Unsupported binary operation");
A
Andrey Breslav 已提交
636
                }
A
Andrey Breslav 已提交
637 638 639
            }
        }

640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
        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)) {
                    semanticServices.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed, use ':' instead");
                }
                else {
                    semanticServices.getErrorHandler().genericError(expression.getOperationSign().getNode(), "This cast can never succeed");
                }
            }
            else {
                if (typeChecker.isSubtypeOf(actualType, targetType)) {
                    semanticServices.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed");
                }
            }
        }

A
Andrey Breslav 已提交
659
        @Override
660 661 662 663 664 665 666 667 668
        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 已提交
669

670 671
        @Override
        public void visitThisExpression(JetThisExpression expression) {
672
            // TODO : qualified this, e.g. this@Foo<Bar>
A
Andrey Breslav 已提交
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
            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) {
689
                    semanticServices.getErrorHandler().unresolvedReference(expression.getTargetLabel());
A
Andrey Breslav 已提交
690 691
                }
                else {
692
                    JetSimpleNameExpression labelElement = expression.getTargetLabel();
A
Andrey Breslav 已提交
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
                    assert labelElement != null;
                    semanticServices.getErrorHandler().genericError(labelElement.getNode(), "Ambiguous label");
                }
            }
            else {
                thisType = scope.getThisType();
            }

            if (thisType != null) {
                if (JetStandardClasses.isNothing(thisType)) {
                    semanticServices.getErrorHandler().genericError(expression.getNode(), "'this' is not defined in this context");
                }
                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();
718
                                TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
A
Andrey Breslav 已提交
719 720
                                for (JetType declaredSupertype : supertypes) {
                                    if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
721
                                        result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
A
Andrey Breslav 已提交
722 723 724 725 726 727
                                        break;
                                    }
                                }
                                if (result == null) {
                                    semanticServices.getErrorHandler().genericError(superTypeElement.getNode(), "Not a superclass");
                                }
728 729
                            }
                        }
A
Andrey Breslav 已提交
730 731
                    } else {
                        result = thisType;
732
                    }
A
Andrey Breslav 已提交
733
                }
A
Andrey Breslav 已提交
734 735 736
            }
        }

737 738
        @Override
        public void visitBlockExpression(JetBlockExpression expression) {
739
            result = getBlockReturnedType(scope, expression.getStatements());
740 741
        }

A
Andrey Breslav 已提交
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
        @Override
        public void visitWhenExpression(JetWhenExpression expression) {
            // TODO :change scope according to the bound value in the when header
            List<JetType> expressions = new ArrayList<JetType>();
            collectAllReturnTypes(expression, scope, expressions);
            result = semanticServices.getTypeChecker().commonSupertype(expressions);
        }

        @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>();
            if (finallyBlock == null) {
                for (JetCatchClause catchClause : catchClauses) {
                    // TODO: change scope here
759 760 761 762
                    JetExpression catchBody = catchClause.getCatchBody();
                    if (catchBody != null) {
                        types.add(getType(scope, catchBody, true));
                    }
A
Andrey Breslav 已提交
763 764 765 766 767 768 769 770 771
                }
            } else {
                types.add(getType(scope, finallyBlock.getFinalExpression(), true));
            }
            types.add(getType(scope, tryBlock, true));
            result = semanticServices.getTypeChecker().commonSupertype(types);
        }

        @Override
772 773 774
        public void visitIfExpression(JetIfExpression expression) {
            checkCondition(scope, expression.getCondition());

775
            // TODO : change types according to is and null checks
776
            JetExpression elseBranch = expression.getElse();
777
            JetExpression thenBranch = expression.getThen();
778 779 780 781 782 783

            if (elseBranch == null) {
                if (thenBranch != null) {
                    getType(scope, thenBranch, true);
                    result = JetStandardClasses.getUnitType();
                }
784
            }
785 786 787 788 789 790
            else if (thenBranch == null) {
                getType(scope, elseBranch, true);
                result = JetStandardClasses.getUnitType();
            }
            else {
                JetType thenType = getType(scope, thenBranch, true);
791
                JetType elseType = getType(scope, elseBranch, true);
792 793 794 795 796 797 798 799 800 801
                if (thenType == null) {
                    result = elseType;
                }
                else if (elseType == null) {
                    result = thenType;
                }
                else {
                    result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
                }
            }
A
Andrey Breslav 已提交
802 803
        }

804 805 806 807 808 809
        private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition) {
            if (condition != null) {
                JetType conditionType = getType(scope, condition, false);

                if (conditionType != null && !isBoolean(conditionType)) {
                    semanticServices.getErrorHandler().genericError(condition.getNode(), "Condition must be of type Boolean, but was of type " + conditionType);
A
Andrey Breslav 已提交
810 811 812 813 814
                }
            }
        }

        @Override
815 816 817 818 819 820 821
        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 已提交
822 823 824
        }

        @Override
825 826
        public void visitDoWhileExpression(JetDoWhileExpression expression) {
            JetExpression body = expression.getBody();
A
Andrey Breslav 已提交
827 828 829 830 831 832
            JetScope conditionScope = scope;
            if (body instanceof JetFunctionLiteralExpression) {
                JetFunctionLiteralExpression function = (JetFunctionLiteralExpression) body;
                if (!function.hasParameterSpecification()) {
                    WritableScope writableScope = semanticServices.createWritableScope(scope, scope.getContainingDeclaration());
                    conditionScope = writableScope;
833
                    getBlockReturnedTypeWithWritableScope(writableScope, function.getBody());
A
Andrey Breslav 已提交
834
                    trace.recordBlock(function);
A
Andrey Breslav 已提交
835 836 837 838 839 840 841
                } else {
                    getType(scope, body, true);
                }
            }
            else if (body != null) {
                WritableScope writableScope = semanticServices.createWritableScope(scope, scope.getContainingDeclaration());
                conditionScope = writableScope;
842
                getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body));
843 844 845 846 847 848 849 850 851
            }
            checkCondition(conditionScope, expression.getCondition());
            result = JetStandardClasses.getUnitType();
        }

        @Override
        public void visitForExpression(JetForExpression expression) {
            JetParameter loopParameter = expression.getLoopParameter();
            JetExpression loopRange = expression.getLoopRange();
852 853 854 855
            JetType loopRangeType = null;
            if (loopRange != null) {
                loopRangeType = getType(scope, loopRange, false);
            }
856 857
            JetType expectedParameterType = null;
            if (loopRangeType != null) {
858 859 860 861 862 863 864
                expectedParameterType = checkIterableConvention(loopRangeType, loopRange.getNode());
            }

            WritableScope loopScope = semanticServices.createWritableScope(scope, scope.getContainingDeclaration());

            if (loopParameter != null) {
                JetTypeReference typeReference = loopParameter.getTypeReference();
865
                VariableDescriptor variableDescriptor;
866
                if (typeReference != null) {
867 868
                    variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, loopParameter);
                    JetType actualParameterType = variableDescriptor.getOutType();
869 870 871 872 873
                    if (expectedParameterType != null &&
                            actualParameterType != null &&
                            !semanticServices.getTypeChecker().isSubtypeOf(expectedParameterType, actualParameterType)) {
                        semanticServices.getErrorHandler().genericError(typeReference.getNode(), "The loop iterates over values of type " + expectedParameterType + " but the parameter is declared to be " + actualParameterType);
                    }
874 875
                }
                else {
876 877
                    if (expectedParameterType == null) {
                        expectedParameterType = ErrorUtils.createErrorType("Error");
878
                    }
879
                    variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), loopParameter, expectedParameterType);
880
                }
881
                loopScope.addVariableDescriptor(variableDescriptor);
882 883
            }

884 885 886 887
            JetExpression body = expression.getBody();
            if (body != null) {
                getType(loopScope, body, true); // TODO
            }
888

889 890 891 892 893 894 895 896 897 898
            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);
899
                if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) {
900 901 902 903 904 905 906 907 908 909 910 911 912 913
                    // TODO : overload resolution rules impose priorities here???
                    semanticServices.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext()' property");
                }
                else if (!hasNextFunctionSupported && !hasNextPropertySupported) {
                    semanticServices.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
                }

                OverloadResolutionResult nextResolutionResult = resolveNoParametersFunction(iteratorType, scope, "next");
                if (nextResolutionResult.isAmbiguity()) {
                    semanticServices.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression");
                } else if (nextResolutionResult.isNothing()) {
                    semanticServices.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().next()' method");
                } else {
                    return nextResolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
914 915 916
                }
            }
            else {
917 918 919
                String errorMessage = "For-loop range must have an iterator() method";
                if (iteratorResolutionResult.isAmbiguity()) {
                    errorMessage = "Method 'iterator()' is ambiguous for this expression";
920
                }
921
                semanticServices.getErrorHandler().genericError(reportErrorsOn, errorMessage);
922
            }
923 924
            return null;
        }
925

926 927 928 929 930 931 932 933 934 935 936
        private boolean checkHasNextFunctionSupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) {
            OverloadResolutionResult hasNextResolutionResult = resolveNoParametersFunction(iteratorType, scope, "hasNext");
            if (hasNextResolutionResult.isAmbiguity()) {
                semanticServices.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().hasNext()' is ambiguous for this expression");
            } else if (hasNextResolutionResult.isNothing()) {
                return false;
            } else {
                JetType hasNextReturnType = hasNextResolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
                if (!isBoolean(hasNextReturnType)) {
                    semanticServices.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext()' method of the loop range must return Boolean, but returns " + hasNextReturnType);
                }
937
            }
938 939
            return true;
        }
940

941
        private boolean checkHasNextPropertySupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) {
942
            VariableDescriptor hasNextProperty = iteratorType.getMemberScope().getVariable("hasNext");
943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
            // TODO :extension properties
            if (hasNextProperty == null) {
                return false;
            } else {
                JetType hasNextReturnType = hasNextProperty.getOutType();
                if (hasNextReturnType == null) {
                    // TODO : accessibility
                    semanticServices.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must be readable");
                }
                else if (!isBoolean(hasNextReturnType)) {
                    semanticServices.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must return Boolean, but returns " + hasNextReturnType);
                }
            }
            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 已提交
963 964 965 966 967 968
        }

        @Override
        public void visitNewExpression(JetNewExpression expression) {
            // TODO : type argument inference
            JetTypeReference typeReference = expression.getTypeReference();
969
            if (typeReference != null) {
970 971 972 973 974 975 976 977 978 979 980 981 982
                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;

983 984 985 986 987 988 989 990 991 992 993 994 995
                        for (JetTypeProjection typeProjection : userType.getTypeArguments()) {
                            switch (typeProjection.getProjectionKind()) {
                                case IN:
                                case OUT:
                                case STAR:
                                    // TODO : Bug in the editor
                                    semanticServices.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments");
                                    break;
                                case NONE:
                                    break;
                            }
                        }

996 997
                        JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
                        if (referenceExpression != null) {
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
                            // 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);
1021
                            OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors);
1022
                            JetType constructorReturnedType = resolveOverloads(
1023
                                    scope,
A
Andrey Breslav 已提交
1024
                                    wrapForTracing(constructorsOverloadDomain, referenceExpression, expression.getValueArgumentList(), false),
1025
                                    Collections.<JetTypeProjection>emptyList(),
A
Andrey Breslav 已提交
1026
                                    expression.getValueArguments(),
1027
                                    expression.getFunctionLiteralArguments());
A
rename  
Andrey Breslav 已提交
1028
                            if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) {
1029 1030
                                trace.recordReferenceResolution(referenceExpression, receiverType.getConstructor().getDeclarationDescriptor());
                                // TODO : more helpful message
A
Andrey Breslav 已提交
1031
                                JetArgumentList argumentList = expression.getValueArgumentList();
1032 1033 1034
                                if (argumentList != null) {
                                    semanticServices.getErrorHandler().genericError(argumentList.getNode(), "Cannot find an overload for these arguments");
                                }
1035
                                constructorReturnedType = receiverType;
1036
                            }
1037 1038 1039 1040
                            // If no upcast needed:
                            result = constructorReturnedType;

                            // Automatic upcast:
1041
//                            result = receiverType;
1042 1043 1044 1045 1046 1047 1048
                        }
                    }
                    else {
                        semanticServices.getErrorHandler().genericError(expression.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : review the message
                    }
                }
                else {
1049 1050 1051
                    if (typeElement != null) {
                        semanticServices.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message
                    }
1052
                }
1053
            }
A
Andrey Breslav 已提交
1054 1055 1056
        }

        @Override
A
Andrey Breslav 已提交
1057 1058 1059 1060 1061 1062
        public void visitHashQualifiedExpression(JetHashQualifiedExpression expression) {
            throw new UnsupportedOperationException(); // TODO
        }

        @Override
        public void visitQualifiedExpression(JetQualifiedExpression expression) {
A
Andrey Breslav 已提交
1063 1064
            // TODO : functions
            JetExpression selectorExpression = expression.getSelectorExpression();
1065
            JetExpression receiverExpression = expression.getReceiverExpression();
A
Andrey Breslav 已提交
1066
            JetType receiverType = getType(scope, receiverExpression, false);
A
Andrey Breslav 已提交
1067 1068
            if (receiverType != null) {
                checkNullSafety(receiverType, expression);
A
Andrey Breslav 已提交
1069 1070 1071 1072 1073 1074 1075
                JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
                if (expression.getOperationSign() == JetTokens.QUEST) {
                    if (selectorReturnType != null && !isBoolean(selectorReturnType)) {
                        // TODO : more comprehensible error message
                        semanticServices.getErrorHandler().typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType);
                    }
                    result = TypeUtils.makeNullable(receiverType);
A
Andrey Breslav 已提交
1076
                }
A
Andrey Breslav 已提交
1077 1078
                else {
                    result = selectorReturnType;
1079
                }
1080 1081 1082
                if (selectorExpression != null && result != null) {
                    trace.recordExpressionType(selectorExpression, result);
                }
A
Andrey Breslav 已提交
1083 1084 1085
            }
        }

A
Andrey Breslav 已提交
1086 1087 1088 1089
        private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) {
            JetScope compositeScope = new ScopeWithReceiver(scope, receiverType);
            if (selectorExpression instanceof JetCallExpression) {
                JetCallExpression callExpression = (JetCallExpression) selectorExpression;
1090
                OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
A
Andrey Breslav 已提交
1091 1092 1093 1094 1095 1096 1097
                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
A
Andrey Breslav 已提交
1098
                semanticServices.getErrorHandler().genericError(selectorExpression.getNode(), "Unsupported selector element type: " + selectorExpression);
A
Andrey Breslav 已提交
1099 1100 1101 1102
            }
            return receiverType;
        }

A
Andrey Breslav 已提交
1103 1104 1105
        @Override
        public void visitCallExpression(JetCallExpression expression) {
            JetExpression calleeExpression = expression.getCalleeExpression();
1106
            OverloadDomain overloadDomain = getOverloadDomain(scope, calleeExpression, expression.getValueArgumentList());
A
Andrey Breslav 已提交
1107
            result = resolveOverloads(scope, expression, overloadDomain);
1108
        }
A
Andrey Breslav 已提交
1109

1110
        @Nullable
A
Andrey Breslav 已提交
1111
        private JetType resolveOverloads(JetScope scope, JetCallExpression expression, OverloadDomain overloadDomain) {
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
            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) {
A
Andrey Breslav 已提交
1125 1126 1127
            // 1) ends with a name -> (scope, name) to look up
            // 2) ends with something else -> just check types

1128 1129 1130 1131 1132
            for (JetTypeProjection typeArgument : typeArguments) {
                if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
                    semanticServices.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
                }
            }
A
Andrey Breslav 已提交
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154

            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
1155 1156 1157 1158
                    JetTypeReference typeReference = projection.getTypeReference();
                    if (typeReference != null) {
                        types.add(typeResolver.resolveType(scope, typeReference));
                    }
A
Andrey Breslav 已提交
1159 1160 1161 1162
                }

                List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
                for (JetArgument argument : valueArguments) {
1163 1164 1165 1166
                    JetExpression argumentExpression = argument.getArgumentExpression();
                    if (argumentExpression != null) {
                        positionedValueArguments.add(argumentExpression);
                    }
A
Andrey Breslav 已提交
1167 1168 1169 1170 1171 1172
                }

                positionedValueArguments.addAll(functionLiteralArguments);

                List<JetType> valueArgumentTypes = new ArrayList<JetType>();
                for (JetExpression valueArgument : positionedValueArguments) {
A
Andrey Breslav 已提交
1173
                    valueArgumentTypes.add(safeGetType(scope, valueArgument, false));
A
Andrey Breslav 已提交
1174 1175
                }

1176 1177 1178
                OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
                if (resolutionResult.isSuccess()) {
                    return resolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
A
Andrey Breslav 已提交
1179 1180
                }
            }
A
Andrey Breslav 已提交
1181
            return null;
A
Andrey Breslav 已提交
1182 1183
        }

A
Andrey Breslav 已提交
1184 1185 1186 1187 1188 1189
        @Override
        public void visitIsExpression(JetIsExpression expression) {
            // TODO : patterns and everything
            result = semanticServices.getStandardLibrary().getBooleanType();
        }

A
Andrey Breslav 已提交
1190
        @Override
1191
        public void visitUnaryExpression(JetUnaryExpression expression) {
A
Andrey Breslav 已提交
1192
            JetSimpleNameExpression operationSign = expression.getOperationSign();
1193 1194 1195 1196 1197
            if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
                // TODO : Some processing for the label?
                result = getType(expression.getBaseExpression());
                return;
            }
A
Andrey Breslav 已提交
1198 1199
            IElementType operationType = operationSign.getReferencedNameElementType();
            String name = unaryOperationNames.get(operationType);
1200
            if (name == null) {
A
Andrey Breslav 已提交
1201
                semanticServices.getErrorHandler().genericError(operationSign.getNode(), "Unknown unary operation");
1202 1203
            }
            else {
A
Andrey Breslav 已提交
1204 1205 1206
                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 已提交
1207
                    if (functionDescriptor != null) {
A
Andrey Breslav 已提交
1208 1209
                        JetType returnType = functionDescriptor.getUnsubstitutedReturnType();
                        if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
1210 1211 1212 1213 1214 1215 1216 1217 1218
                            if (semanticServices.getTypeChecker().isSubtypeOf(returnType, JetStandardClasses.getUnitType())) {
                                 result = JetStandardClasses.getUnitType();
                            }
                            else {
                                if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) {
                                    semanticServices.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType);
                                }
                                // TODO : Maybe returnType?
                                result = receiverType;
A
Andrey Breslav 已提交
1219 1220 1221 1222
                            }
                        } else {
                            result = returnType;
                        }
A
Andrey Breslav 已提交
1223 1224 1225 1226 1227 1228 1229 1230 1231
                    }
                }
            }
        }

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

A
Andrey Breslav 已提交
1232 1233 1234
            JetExpression left = expression.getLeft();
            JetExpression right = expression.getRight();

A
Andrey Breslav 已提交
1235 1236
            IElementType operationType = operationSign.getReferencedNameElementType();
            if (operationType == JetTokens.IDENTIFIER) {
1237 1238 1239 1240
                String referencedName = operationSign.getReferencedName();
                if (referencedName != null) {
                    result = getTypeForBinaryCall(expression, referencedName, scope, true);
                }
A
Andrey Breslav 已提交
1241
            }
1242
            else if (binaryOperationNames.containsKey(operationType)) {
A
Andrey Breslav 已提交
1243
                result = getTypeForBinaryCall(expression, binaryOperationNames.get(operationType), scope, true);
A
Andrey Breslav 已提交
1244 1245
            }
            else if (operationType == JetTokens.EQ) {
A
Andrey Breslav 已提交
1246 1247 1248 1249
                visitAssignment(expression);
            }
            else if (assignmentOperationNames.containsKey(operationType)) {
                visitAssignmentOperation(expression);
A
Andrey Breslav 已提交
1250
            }
1251
            else if (comparisonOperations.contains(operationType)) {
A
Andrey Breslav 已提交
1252
                JetType compareToReturnType = getTypeForBinaryCall(expression, "compareTo", scope, true);
A
Andrey Breslav 已提交
1253 1254 1255 1256 1257 1258 1259
                if (compareToReturnType != null) {
                    TypeConstructor constructor = compareToReturnType.getConstructor();
                    JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
                    TypeConstructor intTypeConstructor = standardLibrary.getInt().getTypeConstructor();
                    if (constructor.equals(intTypeConstructor)) {
                        result = standardLibrary.getBooleanType();
                    } else {
A
Andrey Breslav 已提交
1260
                        semanticServices.getErrorHandler().genericError(operationSign.getNode(), "compareTo must return Int, but returns " + compareToReturnType);
A
Andrey Breslav 已提交
1261
                    }
A
Andrey Breslav 已提交
1262
                }
A
Andrey Breslav 已提交
1263
            }
A
Equals  
Andrey Breslav 已提交
1264
            else if (equalsOperations.contains(operationType)) {
A
Andrey Breslav 已提交
1265
                String name = "equals";
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
                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 {
                                semanticServices.getErrorHandler().genericError(operationSign.getNode(), "No method 'equals(Any?) : Boolean' available");
                            }
                        }
                    }
                }
                result = semanticServices.getStandardLibrary().getBooleanType();
1286 1287 1288 1289 1290 1291
            }
            else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
                ensureNonemptyIntersectionOfOperandTypes(expression);

                // TODO : Check comparison pointlessness
                result = semanticServices.getStandardLibrary().getBooleanType();
A
Andrey Breslav 已提交
1292 1293 1294
            }
            else if (inOperations.contains(operationType)) {
                if (right == null) {
A
rename  
Andrey Breslav 已提交
1295
                    result = ErrorUtils.createErrorType("No right argument"); // TODO
A
Andrey Breslav 已提交
1296
                    return;
A
Andrey Breslav 已提交
1297
                }
A
Andrey Breslav 已提交
1298 1299
                String name = "contains";
                JetType containsType = getTypeForBinaryCall(scope, right, expression.getOperationReference(), expression.getLeft(), name, true);
1300 1301
                ensureBooleanResult(operationSign, name, containsType);
                result = semanticServices.getStandardLibrary().getBooleanType();
A
Equals  
Andrey Breslav 已提交
1302
            }
A
Andrey Breslav 已提交
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313
            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)) {
                    semanticServices.getErrorHandler().typeMismatch(left, semanticServices.getStandardLibrary().getBooleanType(), leftType);
                }
                if (rightType != null && !isBoolean(rightType)) {
                    semanticServices.getErrorHandler().typeMismatch(right, semanticServices.getStandardLibrary().getBooleanType(), rightType);
                }
                result = semanticServices.getStandardLibrary().getBooleanType();
            }
A
Andrey Breslav 已提交
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
            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()) {
                        semanticServices.getErrorHandler().genericWarning(left.getNode(), "Elvis operator (?:) is always returns the left operand of non-nullable type " + leftType);
                    }
                    if (rightType != null) {
                        result = TypeUtils.makeNullableAsSpecified(semanticServices.getTypeChecker().commonSupertype(leftType, rightType), rightType.isNullable());
                    }
                }
            }
A
Equals  
Andrey Breslav 已提交
1326
            else {
A
Andrey Breslav 已提交
1327
                semanticServices.getErrorHandler().genericError(operationSign.getNode(), "Unknown operation");
A
Andrey Breslav 已提交
1328 1329 1330
            }
        }

1331 1332 1333 1334 1335 1336 1337
        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);
1338
            if (leftType != null && right != null) {
1339 1340
                JetType rightType = getType(scope, right, false);

1341 1342 1343 1344 1345
                if (rightType != null) {
                    JetType intersect = TypeUtils.intersect(semanticServices.getTypeChecker(), new HashSet<JetType>(Arrays.asList(leftType, rightType)));
                    if (intersect == null) {
                        semanticServices.getErrorHandler().genericError(expression.getNode(), "Operator " + operationSign.getReferencedName() + " cannot be applied to " + leftType + " and " + rightType);
                    }
1346 1347 1348 1349
                }
            }
        }

A
Andrey Breslav 已提交
1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361
        protected void visitAssignmentOperation(JetBinaryExpression expression) {
            assignmentIsNotAnExpressionError(expression);
        }

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

        private void assignmentIsNotAnExpressionError(JetBinaryExpression expression) {
            semanticServices.getErrorHandler().genericError(expression.getNode(), "Assignments are not expressions, and only expressions are allowed in this context");
        }

1362
        private boolean ensureBooleanResult(JetSimpleNameExpression operationSign, String name, JetType resultType) {
A
Andrey Breslav 已提交
1363 1364
            if (resultType != null) {
                // TODO : Relax?
A
Andrey Breslav 已提交
1365
                if (!isBoolean(resultType)) {
A
Andrey Breslav 已提交
1366
                    semanticServices.getErrorHandler().genericError(operationSign.getNode(), "'" + name + "' must return Boolean but returns " + resultType);
1367
                    return false;
A
Andrey Breslav 已提交
1368 1369
                }
            }
1370
            return true;
A
Andrey Breslav 已提交
1371 1372
        }

A
Andrey Breslav 已提交
1373
        private boolean isBoolean(@NotNull JetType type) {
A
Andrey Breslav 已提交
1374
            return semanticServices.getTypeChecker().isConvertibleTo(type,  semanticServices.getStandardLibrary().getBooleanType());
A
Andrey Breslav 已提交
1375 1376
        }

A
Andrey Breslav 已提交
1377 1378 1379 1380 1381 1382 1383 1384
        @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;

1385 1386 1387 1388 1389
            if (receiverType != null) {
                FunctionDescriptor functionDescriptor = lookupFunction(scope, expression, "get", receiverType, argumentTypes, true);
                if (functionDescriptor != null) {
                    result = functionDescriptor.getUnsubstitutedReturnType();
                }
A
Andrey Breslav 已提交
1390 1391 1392
            }
        }

1393
        @Nullable
1394 1395 1396 1397 1398
        protected JetType getTypeForBinaryCall(
                @NotNull JetBinaryExpression expression,
                @NotNull String name,
                @NotNull JetScope scope,
                boolean reportUnresolved) {
A
Andrey Breslav 已提交
1399 1400 1401
            JetExpression left = expression.getLeft();
            JetExpression right = expression.getRight();
            if (right == null) {
1402
                return null;
A
Andrey Breslav 已提交
1403
            }
A
Andrey Breslav 已提交
1404 1405 1406 1407
            JetSimpleNameExpression operationSign = expression.getOperationReference();
            return getTypeForBinaryCall(scope, left, operationSign, right, name, reportUnresolved);
        }

1408
        @Nullable
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
        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) {
1419 1420
                return null;
            }
A
Andrey Breslav 已提交
1421
            FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType), reportUnresolved);
A
Andrey Breslav 已提交
1422
            if (functionDescriptor != null) {
1423 1424 1425 1426 1427 1428 1429 1430 1431
                if (leftType.isNullable()) {
                    // TODO : better error message for '1 + nullableVar' case
                    semanticServices.getErrorHandler().genericError(operationSign.getNode(),
                            "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 已提交
1432 1433 1434 1435
                return functionDescriptor.getUnsubstitutedReturnType();
            }
            return null;
        }
A
Andrey Breslav 已提交
1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450

        @Override
        public void visitDeclaration(JetDeclaration dcl) {
            semanticServices.getErrorHandler().genericError(dcl.getNode(), "Declarations are not allowed in this position");
        }

        @Override
        public void visitJetElement(JetElement elem) {
            semanticServices.getErrorHandler().genericError(elem.getNode(), "Unsupported element: " + elem + " " + elem.getClass().getCanonicalName());
        }
    }

    private class TypeInferrerVisitorWithWritableScope extends TypeInferrerVisitor {
        private final WritableScope scope;

1451 1452
        public TypeInferrerVisitorWithWritableScope(@NotNull WritableScope scope, boolean preferBlock) {
            super(scope, preferBlock);
A
Andrey Breslav 已提交
1453 1454 1455 1456 1457
            this.scope = scope;
        }

        @Override
        public void visitProperty(JetProperty property) {
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468

            JetPropertyAccessor getter = property.getGetter();
            if (getter != null) {
                semanticServices.getErrorHandler().genericError(getter.getNode(), "Local variables are not allowed to have getters");
            }

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

1469
            VariableDescriptor propertyDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, property);
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
            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)) {
                    semanticServices.getErrorHandler().typeMismatch(initializer, outType, initializerType);
                }
            }

1481
            scope.addVariableDescriptor(propertyDescriptor);
A
Andrey Breslav 已提交
1482 1483 1484 1485
        }

        @Override
        public void visitFunction(JetFunction function) {
1486
            scope.addFunctionDescriptor(classDescriptorResolver.resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function));
A
Andrey Breslav 已提交
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518
        }

        @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);
            }
1519
            result = null; // not an expression
A
Andrey Breslav 已提交
1520 1521 1522 1523 1524
        }

        @Override
        protected void visitAssignment(JetBinaryExpression expression) {
            JetExpression left = expression.getLeft();
1525
            JetExpression deparenthesized = JetPsiUtil.deparenthesize(left);
A
Andrey Breslav 已提交
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
            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)) {
                        semanticServices.getErrorHandler().typeMismatch(right, leftType, rightType);
                    }
                }
            }
A
Andrey Breslav 已提交
1542
            result = null; // This is not an element
A
Andrey Breslav 已提交
1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566
        }

        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) {
            semanticServices.getErrorHandler().genericError(elem.getNode(), "Unsupported element in a block: " + elem + " " + elem.getClass().getCanonicalName());
        }
A
Andrey Breslav 已提交
1567
    }
A
Andrey Breslav 已提交
1568

1569 1570
    private class CachedBindingTrace extends BindingTrace {
        private final BindingTrace originalTrace;
A
Andrey Breslav 已提交
1571

1572 1573 1574
        public CachedBindingTrace(BindingTrace originalTrace) {
            this.originalTrace = originalTrace;
        }
A
Andrey Breslav 已提交
1575

1576 1577 1578 1579
        public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) {
            originalTrace.recordExpressionType(expression, type);
            typeCache.put(expression, type);
        }
A
Andrey Breslav 已提交
1580

1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599
        public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor) {
            originalTrace.recordReferenceResolution(expression, descriptor);
        }

        public void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element) {
            originalTrace.recordLabelResolution(expression, element);
        }

        public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) {
            originalTrace.recordDeclarationResolution(declaration, descriptor);
        }

        public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type) {
            originalTrace.recordTypeResolution(typeReference, type);
        }

        public void setToplevelScope(JetScope toplevelScope) {
            originalTrace.setToplevelScope(toplevelScope);
        }
A
Andrey Breslav 已提交
1600

1601 1602 1603 1604 1605 1606 1607
        public void recordBlock(JetFunctionLiteralExpression expression) {
            originalTrace.recordBlock(expression);
        }

        public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression) {
            originalTrace.removeReferenceResolution(referenceExpression);
        }
A
Andrey Breslav 已提交
1608 1609 1610 1611 1612

        @Override
        public void recordStatement(@NotNull JetElement statement) {
            originalTrace.recordStatement(statement);
        }
1613 1614 1615 1616 1617

        @Override
        public void removeStatementRecord(@NotNull JetElement statement) {
            originalTrace.removeStatementRecord(statement);
        }
A
Andrey Breslav 已提交
1618
    }
1619
}