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

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

import java.util.*;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

133 134 135 136 137 138 139
    @NotNull
    private OverloadResolutionResult resolveNoParametersFunction(@NotNull JetType receiverType, @NotNull JetScope scope, @NotNull String name) {
        OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name);
        // No generics. Guaranteed
        return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<JetType>emptyList(), Collections.<JetType>emptyList());
    }

140
    private OverloadDomain getOverloadDomain(
141
            @Nullable final JetType receiverType,
142 143 144 145
            @NotNull final JetScope scope,
            @NotNull JetExpression calleeExpression,
            @Nullable PsiElement argumentList
    ) {
146
        final OverloadDomain[] result = new OverloadDomain[1];
147
        final JetSimpleNameExpression[] reference = new JetSimpleNameExpression[1];
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
        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) {
164 165
                trace.getErrorHandler().genericError(expression.getNode(), "Unsupported [JetTypeInferrer]");

166
                // . or ?.
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
//                JetType receiverType = getType(scope, expression.getReceiverExpression(), false);
//                checkNullSafety(receiverType, expression.getOperationTokenNode());
//
//                JetExpression selectorExpression = expression.getSelectorExpression();
//                if (selectorExpression instanceof JetSimpleNameExpression) {
//                    JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression;
//                    String referencedName = referenceExpression.getReferencedName();
//
//                    if (receiverType != null && referencedName != null) {
//                        // No generics. Guaranteed
//                        result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
//                        reference[0] = referenceExpression;
//                    }
//                } else {
//                    throw new UnsupportedOperationException(); // TODO
//                }
183 184 185
            }

            @Override
186
            public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
187
                // a -- create a hierarchical lookup domain for this.a
188 189
                String referencedName = expression.getReferencedName();
                if (referencedName != null) {
190
                    // No generics. Guaranteed
191
                    result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
192 193
                    reference[0] = expression;
                }
194 195 196 197 198
            }

            @Override
            public void visitExpression(JetExpression expression) {
                // <e> create a dummy domain for the type of e
199
                throw new UnsupportedOperationException(expression.getText()); // TODO
200 201 202
            }

            @Override
203 204
            public void visitJetElement(JetElement element) {
                trace.getErrorHandler().genericError(element.getNode(), "Unsupported in call element"); // TODO : Message
205 206
            }
        });
207
        return wrapForTracing(result[0], reference[0], argumentList, true);
208 209
    }

210 211
    private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee) {
        if (receiverType != null && callee != null) {
212
            boolean namespaceType = receiverType instanceof NamespaceType;
213 214 215 216
            JetType calleeReceiverType = callee.getReceiverType();
            boolean nullableReceiver = !namespaceType && receiverType.isNullable();
            boolean calleeForbidsNullableReceiver = calleeReceiverType == null || !calleeReceiverType.isNullable();

217
            IElementType operationSign = operationTokenNode.getElementType();
218
            if (nullableReceiver && calleeForbidsNullableReceiver && operationSign == JetTokens.DOT) {
219
                trace.getErrorHandler().genericError(operationTokenNode, "Only safe calls (?.) are allowed on a nullable receiver of type " + receiverType);
A
Andrey Breslav 已提交
220
            }
221
            else if ((!nullableReceiver || !calleeForbidsNullableReceiver) && operationSign == JetTokens.SAFE_ACCESS) {
222
                if (namespaceType) {
223
                    trace.getErrorHandler().genericError(operationTokenNode, "Safe calls are not allowed on namespaces");
224 225
                }
                else {
226
                    trace.getErrorHandler().genericWarning(operationTokenNode, "Unnecessary safe call on a non-null receiver of type  " + receiverType);
227
                }
A
Andrey Breslav 已提交
228 229 230 231
            }
        }
    }

232
    private OverloadDomain wrapForTracing(
233 234
            @NotNull final OverloadDomain overloadDomain,
            @NotNull final JetReferenceExpression referenceExpression,
235
            @Nullable final PsiElement argumentList,
236
            final boolean reportErrors) {
237
        return new OverloadDomain() {
238
            @NotNull
239
            @Override
240 241 242 243
            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;
244 245
            }

246
            @NotNull
247
            @Override
248 249 250 251 252 253 254 255 256 257 258 259 260
            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:
261
                            trace.getErrorHandler().unresolvedReference(referenceExpression);
262 263 264 265
                            break;
                        case SINGLE_FUNCTION_ARGUMENT_MISMATCH:
                            if (argumentList != null) {
                                // TODO : More helpful message. NOTE: there's a separate handling for this for constructors
266
                                trace.getErrorHandler().genericError(argumentList.getNode(), "Arguments do not match " + DescriptorRenderer.TEXT.render(resolutionResult.getFunctionDescriptor()));
267 268
                            }
                            else {
269
                                trace.getErrorHandler().unresolvedReference(referenceExpression);
270 271 272 273 274
                            }
                            break;
                        case AMBIGUITY:
                            if (argumentList != null) {
                                // TODO : More helpful message. NOTE: there's a separate handling for this for constructors
275
                                trace.getErrorHandler().genericError(argumentList.getNode(), "Overload ambiguity [TODO : more helpful message]");
276 277
                            }
                            else {
278
                                trace.getErrorHandler().unresolvedReference(referenceExpression);
279 280 281 282
                            }
                            break;
                        default:
                            // Not a success
283
                    }
A
Andrey Breslav 已提交
284
                }
285 286 287 288 289
            }

            @Override
            public boolean isEmpty() {
                return overloadDomain.isEmpty();
290 291 292 293
            }
        };
    }

294
    @NotNull
295
    public JetType getFunctionReturnType(@NotNull JetScope outerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
296
        Map<JetElement, JetType> typeMap = collectReturnedExpressions(outerScope, function, functionDescriptor);
297 298 299 300
        Collection<JetType> types = typeMap.values();
        return types.isEmpty() ? JetStandardClasses.getNothingType() : semanticServices.getTypeChecker().commonSupertype(types);
    }

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

306
    public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) {
307
        Map<JetElement, JetType> typeMap = collectReturnedExpressions(outerScope, function, functionDescriptor);
308 309 310 311 312 313 314
        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();
315 316 317
            JetTypeChecker typeChecker = semanticServices.getTypeChecker();
            if (!typeChecker.isSubtypeOf(actualType, expectedReturnType)) {
                if (typeChecker.isConvertibleBySpecialConversion(actualType, expectedReturnType)) {
318 319
                    if (expectedReturnType.getConstructor().equals(JetStandardClasses.getUnitType().getConstructor())
                        && element.getParent() instanceof JetReturnExpression) {
320
                        trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type Unit");
321
                    }
322 323
                }
                else {
A
Andrey Breslav 已提交
324 325 326
                    if (element == function) {
                        JetExpression bodyExpression = function.getBodyExpression();
                        assert bodyExpression != null;
327
                        trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType);
A
Andrey Breslav 已提交
328 329
                    }
                    else if (element instanceof JetExpression) {
330
                        JetExpression expression = (JetExpression) element;
331
                        trace.getErrorHandler().typeMismatch(expression, expectedReturnType, actualType);
332 333
                    }
                    else {
334
                        trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type " + expectedReturnType);
335
                    }
336 337 338 339 340
                }
            }
        }
    }

341
    private Map<JetElement, JetType> collectReturnedExpressions(JetScope outerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
342 343
        JetExpression bodyExpression = function.getBodyExpression();
        assert bodyExpression != null;
344
        JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
345 346 347
        getType(functionInnerScope, bodyExpression, function.hasBlockBody());
        Collection<JetExpression> returnedExpressions = new ArrayList<JetExpression>();
        Collection<JetElement> elementsReturningUnit = new ArrayList<JetElement>();
348
        flowInformationProvider.collectReturnedInformation(function.asElement(), returnedExpressions, elementsReturningUnit);
349 350
        Map<JetElement,JetType> typeMap = new HashMap<JetElement, JetType>();
        for (JetExpression returnedExpression : returnedExpressions) {
351
            JetType cachedType = trace.getBindingContext().getExpressionType(returnedExpression);// getCachedType(returnedExpression);
352
            trace.removeStatementRecord(returnedExpression);
353 354 355 356 357 358 359 360 361 362
            if (cachedType != null) {
                typeMap.put(returnedExpression, cachedType);
            }
        }
        for (JetElement jetElement : elementsReturningUnit) {
            typeMap.put(jetElement, JetStandardClasses.getUnitType());
        }
        return typeMap;
    }

363
    @Nullable
364
    private JetType getBlockReturnedType(@NotNull JetScope outerScope, @NotNull List<JetElement> block) {
365 366
        if (block.isEmpty()) {
            return JetStandardClasses.getUnitType();
A
Andrey Breslav 已提交
367
        }
A
Andrey Breslav 已提交
368 369

        DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration();
A
Cleanup  
Andrey Breslav 已提交
370
        WritableScope scope = new WritableScopeImpl(outerScope, containingDescriptor, trace.getErrorHandler());
371
        return getBlockReturnedTypeWithWritableScope(scope, block);
A
Andrey Breslav 已提交
372 373
    }

374
    private JetType getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List<? extends JetElement> block) {
375 376 377
        if (block.isEmpty()) {
            return JetStandardClasses.getUnitType();
        }
A
Andrey Breslav 已提交
378

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

A
Andrey Breslav 已提交
381 382
        JetType result = null;
        for (JetElement statement : block) {
383 384 385
            trace.recordStatement(statement);
            JetExpression statementExpression = (JetExpression) statement;
            result = blockLevelVisitor.getType(statementExpression);
A
Andrey Breslav 已提交
386
            blockLevelVisitor.resetResult(); // TODO : maybe it's better to recreate the visitors with the same scope?
387
        }
A
Andrey Breslav 已提交
388
        return result;
389 390
    }

A
Andrey Breslav 已提交
391
    private void collectAllReturnTypes(JetWhenExpression whenExpression, JetScope scope, List<JetType> result) {
392 393 394 395 396 397 398
        for (JetWhenEntry entry : whenExpression.getEntries()) {
            JetWhenExpression subWhen = entry.getSubWhen();
            if (subWhen != null) {
                collectAllReturnTypes(subWhen, scope, result);
            } else {
                JetExpression resultExpression = entry.getExpression();
                if (resultExpression != null) {
399 400 401 402
                    JetType type = getType(scope, resultExpression, true);
                    if (type != null) {
                        result.add(type);
                    }
403 404 405 406 407
                }
            }
        }
    }

408
    @Nullable
A
Andrey Breslav 已提交
409
    private JetType resolveCall(
410 411
            @NotNull JetScope scope,
            @NotNull OverloadDomain overloadDomain,
A
Andrey Breslav 已提交
412
            @NotNull JetCall call) {
413 414 415
        // 1) ends with a name -> (scope, name) to look up
        // 2) ends with something else -> just check types

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

418
        for (JetTypeProjection typeArgument : jetTypeArguments) {
419
            if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
420
                trace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
421 422 423
            }
        }

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

426 427 428 429 430 431 432 433
        boolean someNamed = false;
        for (JetArgument argument : valueArguments) {
            if (argument.isNamed()) {
                someNamed = true;
                break;
            }
        }

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

436 437 438 439 440 441 442 443 444
        // 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 {
445 446
            List<JetType> typeArguments = new ArrayList<JetType>();
            for (JetTypeProjection projection : jetTypeArguments) {
447 448 449
                // TODO : check that there's no projection
                JetTypeReference typeReference = projection.getTypeReference();
                if (typeReference != null) {
450
                    typeArguments.add(typeResolver.resolveType(scope, typeReference));
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
                }
            }

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

            positionedValueArguments.addAll(functionLiteralArguments);

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

469
            OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, valueArgumentTypes);
470
            if (resolutionResult.isSuccess()) {
471 472
                final FunctionDescriptor functionDescriptor = resolutionResult.getFunctionDescriptor();

473
                checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, functionDescriptor);
474
                return functionDescriptor.getUnsubstitutedReturnType();
475 476 477 478 479
            }
        }
        return null;
    }

480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
    private void checkGenericBoundsInAFunctionCall(List<JetTypeProjection> jetTypeArguments, List<JetType> typeArguments, FunctionDescriptor functionDescriptor) {
        Map<TypeConstructor, TypeProjection> context = Maps.newHashMap();

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

499
    @Nullable
500
    public JetType checkConstructorCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) {
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
        JetTypeElement typeElement = typeReference.getTypeElement();
        if (typeElement instanceof JetUserType) {
            JetUserType userType = (JetUserType) typeElement;
            // TODO : to infer constructor parameters, one will need to
            //  1) resolve a _class_ from the typeReference
            //  2) rely on the overload domain of constructors of this class to infer type arguments
            // For now we assume that the type arguments are provided, and thus the typeReference can be
            // resolved into a valid type
            JetType receiverType = typeResolver.resolveType(scope, typeReference);
            DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor();
            if (declarationDescriptor instanceof ClassDescriptor) {
                ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;

                for (JetTypeProjection typeProjection : userType.getTypeArguments()) {
                    switch (typeProjection.getProjectionKind()) {
                        case IN:
                        case OUT:
                        case STAR:
                            // TODO : Bug in the editor
520
                            trace.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments");
521 522 523 524 525 526 527 528
                            break;
                        case NONE:
                            break;
                    }
                }

                JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
                if (referenceExpression != null) {
529
                    return checkClassConstructorCall(scope, referenceExpression, classDescriptor, receiverType, call);
530 531 532
                }
            }
            else {
533
                trace.getErrorHandler().genericError(((JetElement) call).getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : review the message
534
            }
535
            return null;
536 537 538
        }
        else {
            if (typeElement != null) {
539
                trace.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message
540 541 542 543 544
            }
        }
        return null;
    }

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

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

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

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

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

602 603 604

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

A
Andrey Breslav 已提交
605
    private class TypeInferrerVisitor extends JetVisitor {
606
        protected final JetScope scope;
A
Andrey Breslav 已提交
607
        private final boolean preferBlock;
A
Andrey Breslav 已提交
608

609
        protected JetType result;
A
Andrey Breslav 已提交
610

611
        private TypeInferrerVisitor(@NotNull JetScope scope, boolean preferBlock) {
A
Andrey Breslav 已提交
612 613 614 615
            this.scope = scope;
            this.preferBlock = preferBlock;
        }

616 617 618 619 620 621 622
        @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 {
623
                visitor = createNew(scope, preferBlock);
624 625 626 627 628 629
            }
            JetType type = visitor.getType(expression);
            visitor.result = null;
            return type;
        }

630 631 632 633 634
        @NotNull
        public TypeInferrerVisitor createNew(JetScope scope, boolean preferBlock) {
            return new TypeInferrerVisitor(scope, preferBlock);
        }

635
        @Nullable
636
        public final JetType getType(@NotNull JetExpression expression) {
637
            assert result == null;
638 639 640
            if (trace.isProcessed(expression)) {
                return trace.getBindingContext().getExpressionType(expression);
            }
641 642
            try {
                expression.accept(this);
643 644 645
                if (result instanceof DeferredType) {
                    result = ((DeferredType) result).getActualType();
                }
646 647 648 649 650
                if (result != null) {
                    trace.recordExpressionType(expression, result);
                    if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
                        markDominatedExpressionsAsUnreachable(expression);
                    }
651
                }
652
            }
653 654 655 656
            catch (ReenteringLazyValueComputationException e) {
                trace.getErrorHandler().genericError(expression.getNode(), "Type inference has run into a recursive problem"); // TODO : message
                result = null;
            }
657

658
            trace.markAsProcessed(expression);
A
Andrey Breslav 已提交
659 660 661
            return result;
        }

662 663 664 665
        public void resetResult() {
            result = null;
        }

666 667 668 669 670 671 672
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

A
Andrey Breslav 已提交
678 679
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

A
Andrey Breslav 已提交
680
        @Override
681
        public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
A
Andrey Breslav 已提交
682 683
            // TODO : other members
            // TODO : type substitutions???
684 685 686 687
            String referencedName = expression.getReferencedName();
            if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
                    && referencedName != null) {
                PropertyDescriptor property = scope.getPropertyByFieldReference(referencedName);
A
Andrey Breslav 已提交
688
                if (property == null) {
689
                    trace.getErrorHandler().unresolvedReference(expression);
A
Andrey Breslav 已提交
690 691 692 693 694 695 696 697 698 699 700 701 702 703
                }
                else {
                    trace.recordReferenceResolution(expression, property);
                    result = property.getOutType();
                }
            }
            else {
                assert  expression.getReferencedNameElementType() == JetTokens.IDENTIFIER;
                if (referencedName != null) {
                    VariableDescriptor variable = scope.getVariable(referencedName);
                    if (variable != null) {
                        trace.recordReferenceResolution(expression, variable);
                        result = variable.getOutType();
                        if (result == null) {
704
                            trace.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context");
A
Andrey Breslav 已提交
705
                        }
706
                        return;
707 708
                    } else if (furtherNameLookup(expression, referencedName)) {
                        return;
709
                    }
710
                    trace.getErrorHandler().unresolvedReference(expression);
A
Andrey Breslav 已提交
711 712 713 714
                }
            }
        }

715 716 717
        protected boolean furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) {
            NamespaceType namespaceType = lookupNamespaceType(expression, referencedName);
            if (namespaceType != null) {
718
                trace.getErrorHandler().genericError(expression.getNode(), "Expression expected, but a namespace name found");
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
                return true;
            }
            return false;
        }

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

734
        @Override
735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
        public void visitObjectLiteralExpression(final JetObjectLiteralExpression expression) {
            TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, new BindingTraceAdapter(trace) {
                @Override
                public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) {
                    if (declaration == expression.getObjectDeclaration()) {
                        JetType defaultType = ((ClassDescriptor) descriptor).getDefaultType();
                        result = defaultType;
                        if (!trace.isProcessed(expression)) {
                            recordExpressionType(expression, defaultType);
                            markAsProcessed(expression);
                        }
                    }
                    super.recordDeclarationResolution(declaration, descriptor);
                }
            });
750 751 752
            topDownAnalyzer.processObject(scope, scope.getContainingDeclaration(), expression.getObjectDeclaration());
        }

A
Andrey Breslav 已提交
753 754 755
        @Override
        public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
            if (preferBlock && !expression.hasParameterSpecification()) {
756
                trace.recordBlock(expression);
757
                result = getBlockReturnedType(scope, expression.getBody());
A
Andrey Breslav 已提交
758 759 760 761 762 763 764 765 766 767 768
                return;
            }

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

769 770 771
            FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(
                    scope.getContainingDeclaration(), Collections.<Annotation>emptyList(), "<anonymous>");

A
Andrey Breslav 已提交
772
            List<JetType> parameterTypes = new ArrayList<JetType>();
773 774 775 776
            List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList();
            List<JetParameter> parameters = expression.getParameters();
            for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
                JetParameter parameter = parameters.get(i);
A
Andrey Breslav 已提交
777
                JetTypeReference typeReference = parameter.getTypeReference();
778 779 780 781 782 783 784 785

                JetType type;
                if (typeReference != null) {
                    type = typeResolver.resolveType(scope, typeReference);
                }
                else {
                    trace.getErrorHandler().genericError(parameter.getNode(), "Type inference for parameters is not implemented yet");
                    type = ErrorUtils.createErrorType("Not inferred");
A
Andrey Breslav 已提交
786
                }
787 788 789
                ValueParameterDescriptor valueParameterDescriptor = classDescriptorResolver.resolveValueParameterDescriptor(functionDescriptor, parameter, i, type);
                parameterTypes.add(valueParameterDescriptor.getOutType());
                valueParameterDescriptors.add(valueParameterDescriptor);
A
Andrey Breslav 已提交
790
            }
791 792 793 794 795 796

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

            JetTypeReference returnTypeRef = expression.getReturnTypeRef();
A
Andrey Breslav 已提交
797 798 799 800
            JetType returnType;
            if (returnTypeRef != null) {
                returnType = typeResolver.resolveType(scope, returnTypeRef);
            } else {
A
Cleanup  
Andrey Breslav 已提交
801
                WritableScope writableScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler());
802
                for (VariableDescriptor variableDescriptor : valueParameterDescriptors) {
803
                    writableScope.addVariableDescriptor(variableDescriptor);
A
Andrey Breslav 已提交
804 805
                }
                writableScope.setThisType(receiverType);
806
                returnType = getBlockReturnedType(writableScope, expression.getBody());
A
Andrey Breslav 已提交
807
            }
808
            JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType;
809 810 811
            functionDescriptor.setReturnType(safeReturnType);


812
            result = JetStandardClasses.getFunctionType(Collections.<Annotation>emptyList(), effectiveReceiverType, parameterTypes, safeReturnType);
A
Andrey Breslav 已提交
813 814 815 816
        }

        @Override
        public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
817 818 819 820
            JetExpression inner = expression.getExpression();
            if (inner != null) {
                result = getType(scope, inner, false);
            }
A
Andrey Breslav 已提交
821 822 823 824 825 826 827
        }

        @Override
        public void visitConstantExpression(JetConstantExpression expression) {
            IElementType elementType = expression.getNode().getElementType();
            JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
            if (elementType == JetNodeTypes.INTEGER_CONSTANT) {
828 829
                Object value = expression.getValue();
                if (value == null) {
830
                    trace.getErrorHandler().genericError(expression.getNode(), "Number is of range for Long");
831 832
                }
                else if (value instanceof Long) {
A
Andrey Breslav 已提交
833 834 835 836 837 838
                    result = standardLibrary.getLongType();
                }
                else {
                    result = standardLibrary.getIntType();
                }
                // TODO : other ranges
A
Cleanup  
Andrey Breslav 已提交
839 840
            }
            else if (elementType == JetNodeTypes.LONG_CONSTANT) {
A
Andrey Breslav 已提交
841
                result = standardLibrary.getLongType();
A
Cleanup  
Andrey Breslav 已提交
842 843
            }
            else if (elementType == JetNodeTypes.FLOAT_CONSTANT) {
A
Andrey Breslav 已提交
844 845 846 847 848
                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 已提交
849 850
                }
                else {
A
Andrey Breslav 已提交
851 852
                    result = standardLibrary.getDoubleType();
                }
A
Cleanup  
Andrey Breslav 已提交
853 854
            }
            else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) {
A
Andrey Breslav 已提交
855
                result = standardLibrary.getBooleanType();
A
Cleanup  
Andrey Breslav 已提交
856 857
            }
            else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) {
A
Andrey Breslav 已提交
858
                result = standardLibrary.getCharType();
A
Cleanup  
Andrey Breslav 已提交
859 860
            }
            else if (elementType == JetNodeTypes.STRING_CONSTANT) {
A
Andrey Breslav 已提交
861
                result = standardLibrary.getStringType();
A
Cleanup  
Andrey Breslav 已提交
862 863
            }
            else if (elementType == JetNodeTypes.NULL) {
A
Andrey Breslav 已提交
864
                result = JetStandardClasses.getNullableNothingType();
A
Cleanup  
Andrey Breslav 已提交
865 866
            }
            else {
A
Andrey Breslav 已提交
867 868 869 870 871 872
                throw new IllegalArgumentException("Unsupported constant: " + expression);
            }
        }

        @Override
        public void visitThrowExpression(JetThrowExpression expression) {
A
Andrey Breslav 已提交
873 874 875 876 877
            JetExpression thrownExpression = expression.getThrownExpression();
            if (thrownExpression != null) {
                JetType type = getType(scope, thrownExpression, false);
                // TODO : check that it inherits Throwable
            }
A
Andrey Breslav 已提交
878 879 880 881 882 883
            result = JetStandardClasses.getNothingType();
        }

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

A
Andrey Breslav 已提交
885
            if (returnedExpression != null) {
A
Cleanup  
Andrey Breslav 已提交
886
                getType(scope, returnedExpression, false);
A
Andrey Breslav 已提交
887 888
            }

A
Andrey Breslav 已提交
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
            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 已提交
904 905
            JetType type = safeGetType(scope, expression.getBaseExpression(), false);
            result = semanticServices.getStandardLibrary().getTypeInfoType(type);
A
Andrey Breslav 已提交
906 907 908 909
        }

        @Override
        public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) {
A
Andrey Breslav 已提交
910 911 912 913 914 915 916
            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)) {
917
                        trace.getErrorHandler().typeMismatch(expression.getLeft(), targetType, actualType);
A
Andrey Breslav 已提交
918
                    }
A
Andrey Breslav 已提交
919
                    result = targetType;
A
Andrey Breslav 已提交
920
                }
A
Andrey Breslav 已提交
921
                else if (operationType == JetTokens.AS_KEYWORD) {
922
                    checkForCastImpossibility(expression, actualType, targetType);
A
Andrey Breslav 已提交
923 924 925
                    result = targetType;
                }
                else if (operationType == JetTokens.AS_SAFE) {
926
                    checkForCastImpossibility(expression, actualType, targetType);
A
Andrey Breslav 已提交
927
                    result = TypeUtils.makeNullable(targetType);
A
Andrey Breslav 已提交
928 929
                }
                else {
930
                    trace.getErrorHandler().genericError(expression.getOperationSign().getNode(), "Unsupported binary operation");
A
Andrey Breslav 已提交
931
                }
A
Andrey Breslav 已提交
932 933 934
            }
        }

935 936 937 938 939 940
        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)) {
941
                    trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed, use ':' instead");
942 943
                }
                else {
944 945
                    // See JET-58 Make 'as never succeeds' a warning, or even never check for Java (external) types
                    trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "This cast can never succeed");
946 947 948 949
                }
            }
            else {
                if (typeChecker.isSubtypeOf(actualType, targetType)) {
950
                    trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed");
951 952 953 954
                }
            }
        }

A
Andrey Breslav 已提交
955
        @Override
956 957 958 959
        public void visitTupleExpression(JetTupleExpression expression) {
            List<JetExpression> entries = expression.getEntries();
            List<JetType> types = new ArrayList<JetType>();
            for (JetExpression entry : entries) {
960
                types.add(safeGetType(scope, entry, false));
961 962 963 964
            }
            // TODO : labels
            result = JetStandardClasses.getTupleType(types);
        }
A
Andrey Breslav 已提交
965

966 967
        @Override
        public void visitThisExpression(JetThisExpression expression) {
A
Andrey Breslav 已提交
968 969 970 971 972
            JetType thisType = null;
            String labelName = expression.getLabelName();
            if (labelName != null) {
                Collection<DeclarationDescriptor> declarationsByLabel = scope.getDeclarationsByLabel(labelName);
                int size = declarationsByLabel.size();
A
Andrey Breslav 已提交
973 974
                final JetSimpleNameExpression targetLabel = expression.getTargetLabel();
                assert targetLabel != null;
A
Andrey Breslav 已提交
975 976 977 978 979
                if (size == 1) {
                    DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
                    if (declarationDescriptor instanceof ClassDescriptor) {
                        ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
                        thisType = classDescriptor.getDefaultType();
980 981 982 983
                    }
                    else if (declarationDescriptor instanceof FunctionDescriptor) {
                        FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
                        thisType = functionDescriptor.getReceiverType();
A
Andrey Breslav 已提交
984 985 986 987
                    }
                    else {
                        throw new UnsupportedOperationException(); // TODO
                    }
988 989
                    trace.recordReferenceResolution(targetLabel, declarationDescriptor);
                    trace.recordReferenceResolution(expression.getThisReference(), declarationDescriptor);
A
Andrey Breslav 已提交
990 991
                }
                else if (size == 0) {
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
                    // This uses the info written by the control flow processor
                    PsiElement psiElement = trace.getBindingContext().resolveToDeclarationPsiElement(targetLabel);
                    if (psiElement instanceof JetFunctionLiteralExpression) {
                        DeclarationDescriptor declarationDescriptor = trace.getBindingContext().getDeclarationDescriptor(psiElement);
                        if (declarationDescriptor instanceof FunctionDescriptor) {
                            thisType = ((FunctionDescriptor) declarationDescriptor).getReceiverType();
                            if (thisType == null) {
                                thisType = JetStandardClasses.getNothingType();
                            }
                            else {
                                trace.recordReferenceResolution(targetLabel, declarationDescriptor);
                                trace.recordReferenceResolution(expression.getThisReference(), declarationDescriptor);
                            }
                        }
                        else {
                            trace.getErrorHandler().unresolvedReference(targetLabel);
                        }
                    }
                    else {
                        trace.getErrorHandler().unresolvedReference(targetLabel);
                    }
A
Andrey Breslav 已提交
1013 1014
                }
                else {
A
Andrey Breslav 已提交
1015
                    trace.getErrorHandler().genericError(targetLabel.getNode(), "Ambiguous label");
A
Andrey Breslav 已提交
1016 1017 1018 1019
                }
            }
            else {
                thisType = scope.getThisType();
A
Andrey Breslav 已提交
1020 1021 1022 1023 1024

                DeclarationDescriptor declarationDescriptorForUnqualifiedThis = scope.getDeclarationDescriptorForUnqualifiedThis();
                if (declarationDescriptorForUnqualifiedThis != null) {
                    trace.recordReferenceResolution(expression.getThisReference(), declarationDescriptorForUnqualifiedThis);
                }
A
Andrey Breslav 已提交
1025 1026 1027 1028
            }

            if (thisType != null) {
                if (JetStandardClasses.isNothing(thisType)) {
1029
                    trace.getErrorHandler().genericError(expression.getNode(), "'this' is not defined in this context");
A
Andrey Breslav 已提交
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
                }
                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();
1044
                                TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
A
Andrey Breslav 已提交
1045 1046
                                for (JetType declaredSupertype : supertypes) {
                                    if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
1047
                                        result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT);
A
Andrey Breslav 已提交
1048 1049 1050 1051
                                        break;
                                    }
                                }
                                if (result == null) {
1052
                                    trace.getErrorHandler().genericError(superTypeElement.getNode(), "Not a superclass");
A
Andrey Breslav 已提交
1053
                                }
1054 1055
                            }
                        }
A
Andrey Breslav 已提交
1056 1057
                    } else {
                        result = thisType;
1058
                    }
A
Andrey Breslav 已提交
1059 1060 1061
                    if (result != null) {
                        trace.recordExpressionType(expression.getThisReference(), result);
                    }
A
Andrey Breslav 已提交
1062
                }
A
Andrey Breslav 已提交
1063 1064 1065
            }
        }

1066 1067
        @Override
        public void visitBlockExpression(JetBlockExpression expression) {
1068
            result = getBlockReturnedType(scope, expression.getStatements());
1069 1070
        }

A
Andrey Breslav 已提交
1071
        @Override
1072
        public void visitWhenExpression(final JetWhenExpression expression) {
A
Andrey Breslav 已提交
1073
            // TODO :change scope according to the bound value in the when header
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
            final JetExpression subjectExpression = expression.getSubjectExpression();

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

            // TODO : exhaustive patterns

            for (JetWhenEntry whenEntry : expression.getEntries()) {
1084
                final JetType finalSubjectType = subjectType != null ? subjectType : ErrorUtils.createErrorType("Unknown type");
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
                JetWhenCondition condition = whenEntry.getCondition();
                if (condition != null) {
                    condition.accept(new JetVisitor() {
                        @Override
                        public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
                            JetExpression conditionExpression = condition.getExpression();
                            if (conditionExpression != null) {
                                JetType type = getType(scope, conditionExpression, false);
                                if (type != null && finalSubjectType != null) {
                                    if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(finalSubjectType, type)) == null) {
                                        trace.getErrorHandler().genericError(conditionExpression.getNode(), "This condition can never hold");
                                    }
                                }
                            }
                        }

                        @Override
                        public void visitWhenConditionCall(JetWhenConditionCall condition) {
                            JetExpression callSuffixExpression = condition.getCallSuffixExpression();
1104
                            JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType, semanticServices.getTypeChecker());
1105 1106 1107
                            if (callSuffixExpression != null) {
                                JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false);
                                ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression");
1108
                                checkNullSafety(finalSubjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression));
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
                            }
                        }

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

                        @Override
                        public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
1122 1123 1124 1125
                            JetPattern pattern = condition.getPattern();
                            if (pattern != null) {
                                checkPatternType(pattern, finalSubjectType);
                            }
1126 1127 1128
                        }

                        @Override
1129 1130
                        public void visitJetElement(JetElement element) {
                            trace.getErrorHandler().genericError(element.getNode(), "Unsupported [JetTypeInferrer] : " + element);
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
                        }
                    });
                }
            }

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

1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
        private void checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType) {
            pattern.accept(new JetVisitor() {
                @Override
                public void visitTypePattern(JetTypePattern typePattern) {
                    JetTypeReference typeReference = typePattern.getTypeReference();
                    if (typeReference != null) {
                        JetType type = typeResolver.resolveType(scope, typeReference);
                        checkTypeCompatibility(type, subjectType, typePattern);
                    }
                }

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

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

                @Override
                public void visitTuplePattern(JetTuplePattern pattern) {
                    List<JetTuplePatternEntry> entries = pattern.getEntries();
                    TypeConstructor typeConstructor = subjectType.getConstructor();
                    if (!JetStandardClasses.getTuple(entries.size()).getTypeConstructor().equals(typeConstructor)
                            || typeConstructor.getParameters().size() != entries.size()) {
1174
                        trace.getErrorHandler().genericError(pattern.getNode(), "Type mismatch: subject is of type " + subjectType + " but the pattern is of type Tuple" + entries.size()); // TODO : message
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
                    }
                    else {
                        for (int i = 0, entriesSize = entries.size(); i < entriesSize; i++) {
                            JetTuplePatternEntry entry = entries.get(i);
                            JetType type = subjectType.getArguments().get(i).getType();

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

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

1195 1196 1197 1198 1199 1200 1201
                @Override
                public void visitDecomposerPattern(JetDecomposerPattern pattern) {
                    JetType selectorReturnType = getSelectorReturnType(subjectType, pattern.getDecomposerExpression());

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

1202 1203 1204 1205 1206 1207 1208 1209 1210 1211
                private void checkTypeCompatibility(@Nullable JetType type, @NotNull JetType subjectType, @NotNull JetElement reportErrorOn) {
                    if (type == null) {
                        return;
                    }
                    if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) {
                        trace.getErrorHandler().genericError(reportErrorOn.getNode(), "Incompatible types: " + type + " and " + subjectType); // TODO : message
                    }
                }

                @Override
1212 1213
                public void visitJetElement(JetElement element) {
                    trace.getErrorHandler().genericError(element.getNode(), "Unsupported [JetTypeInferrer]");
1214 1215 1216 1217
                }
            });
        }

A
Andrey Breslav 已提交
1218 1219 1220 1221 1222 1223
        @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>();
1224 1225 1226 1227 1228
            for (JetCatchClause catchClause : catchClauses) {
                JetParameter catchParameter = catchClause.getCatchParameter();
                JetExpression catchBody = catchClause.getCatchBody();
                if (catchParameter != null) {
                    VariableDescriptor variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, catchParameter);
1229
                    if (catchBody != null) {
A
Cleanup  
Andrey Breslav 已提交
1230
                        WritableScope catchScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
1231 1232 1233 1234 1235
                        catchScope.addVariableDescriptor(variableDescriptor);
                        JetType type = getType(catchScope, catchBody, true);
                        if (type != null) {
                            types.add(type);
                        }
1236
                    }
A
Andrey Breslav 已提交
1237 1238
                }
            }
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
            if (finallyBlock != null) {
                types.clear(); // Do not need the list for the check, but need the code above to typecheck catch bodies
                JetType type = getType(scope, finallyBlock.getFinalExpression(), true);
                if (type != null) {
                    types.add(type);
                }
            }
            JetType type = getType(scope, tryBlock, true);
            if (type != null) {
                types.add(type);
            }
            if (types.isEmpty()) {
                result = null;
            }
            else {
                result = semanticServices.getTypeChecker().commonSupertype(types);
            }
A
Andrey Breslav 已提交
1256 1257 1258
        }

        @Override
1259 1260 1261
        public void visitIfExpression(JetIfExpression expression) {
            checkCondition(scope, expression.getCondition());

1262
            // TODO : change types according to is and null checks
1263
            JetExpression elseBranch = expression.getElse();
1264
            JetExpression thenBranch = expression.getThen();
1265 1266 1267 1268 1269 1270

            if (elseBranch == null) {
                if (thenBranch != null) {
                    getType(scope, thenBranch, true);
                    result = JetStandardClasses.getUnitType();
                }
1271
            }
1272 1273 1274 1275 1276 1277
            else if (thenBranch == null) {
                getType(scope, elseBranch, true);
                result = JetStandardClasses.getUnitType();
            }
            else {
                JetType thenType = getType(scope, thenBranch, true);
1278
                JetType elseType = getType(scope, elseBranch, true);
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288
                if (thenType == null) {
                    result = elseType;
                }
                else if (elseType == null) {
                    result = thenType;
                }
                else {
                    result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
                }
            }
A
Andrey Breslav 已提交
1289 1290
        }

1291 1292 1293 1294 1295
        private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition) {
            if (condition != null) {
                JetType conditionType = getType(scope, condition, false);

                if (conditionType != null && !isBoolean(conditionType)) {
1296
                    trace.getErrorHandler().genericError(condition.getNode(), "Condition must be of type Boolean, but was of type " + conditionType);
A
Andrey Breslav 已提交
1297 1298 1299 1300 1301
                }
            }
        }

        @Override
1302 1303 1304 1305 1306 1307 1308
        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 已提交
1309 1310 1311
        }

        @Override
1312 1313
        public void visitDoWhileExpression(JetDoWhileExpression expression) {
            JetExpression body = expression.getBody();
A
Andrey Breslav 已提交
1314 1315 1316 1317
            JetScope conditionScope = scope;
            if (body instanceof JetFunctionLiteralExpression) {
                JetFunctionLiteralExpression function = (JetFunctionLiteralExpression) body;
                if (!function.hasParameterSpecification()) {
A
Cleanup  
Andrey Breslav 已提交
1318
                    WritableScope writableScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
A
Andrey Breslav 已提交
1319
                    conditionScope = writableScope;
1320
                    getBlockReturnedTypeWithWritableScope(writableScope, function.getBody());
A
Andrey Breslav 已提交
1321
                    trace.recordBlock(function);
A
Andrey Breslav 已提交
1322 1323 1324 1325 1326
                } else {
                    getType(scope, body, true);
                }
            }
            else if (body != null) {
A
Cleanup  
Andrey Breslav 已提交
1327
                WritableScope writableScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
A
Andrey Breslav 已提交
1328
                conditionScope = writableScope;
1329
                getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body));
1330 1331 1332 1333 1334 1335 1336 1337 1338
            }
            checkCondition(conditionScope, expression.getCondition());
            result = JetStandardClasses.getUnitType();
        }

        @Override
        public void visitForExpression(JetForExpression expression) {
            JetParameter loopParameter = expression.getLoopParameter();
            JetExpression loopRange = expression.getLoopRange();
1339 1340 1341 1342
            JetType loopRangeType = null;
            if (loopRange != null) {
                loopRangeType = getType(scope, loopRange, false);
            }
1343 1344
            JetType expectedParameterType = null;
            if (loopRangeType != null) {
1345 1346 1347
                expectedParameterType = checkIterableConvention(loopRangeType, loopRange.getNode());
            }

A
Cleanup  
Andrey Breslav 已提交
1348
            WritableScope loopScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler());
1349 1350 1351

            if (loopParameter != null) {
                JetTypeReference typeReference = loopParameter.getTypeReference();
1352
                VariableDescriptor variableDescriptor;
1353
                if (typeReference != null) {
1354 1355
                    variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, loopParameter);
                    JetType actualParameterType = variableDescriptor.getOutType();
1356 1357 1358
                    if (expectedParameterType != null &&
                            actualParameterType != null &&
                            !semanticServices.getTypeChecker().isSubtypeOf(expectedParameterType, actualParameterType)) {
1359
                        trace.getErrorHandler().genericError(typeReference.getNode(), "The loop iterates over values of type " + expectedParameterType + " but the parameter is declared to be " + actualParameterType);
1360
                    }
1361 1362
                }
                else {
1363 1364
                    if (expectedParameterType == null) {
                        expectedParameterType = ErrorUtils.createErrorType("Error");
1365
                    }
1366
                    variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), loopParameter, expectedParameterType);
1367
                }
1368
                loopScope.addVariableDescriptor(variableDescriptor);
1369 1370
            }

1371 1372 1373 1374
            JetExpression body = expression.getBody();
            if (body != null) {
                getType(loopScope, body, true); // TODO
            }
1375

1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
            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);
1386
                if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) {
1387
                    // TODO : overload resolution rules impose priorities here???
1388
                    trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext()' property");
1389 1390
                }
                else if (!hasNextFunctionSupported && !hasNextPropertySupported) {
1391
                    trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
1392 1393 1394 1395
                }

                OverloadResolutionResult nextResolutionResult = resolveNoParametersFunction(iteratorType, scope, "next");
                if (nextResolutionResult.isAmbiguity()) {
1396
                    trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression");
1397
                } else if (nextResolutionResult.isNothing()) {
1398
                    trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().next()' method");
1399 1400
                } else {
                    return nextResolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
1401 1402 1403
                }
            }
            else {
1404 1405 1406
                String errorMessage = "For-loop range must have an iterator() method";
                if (iteratorResolutionResult.isAmbiguity()) {
                    errorMessage = "Method 'iterator()' is ambiguous for this expression";
1407
                }
1408
                trace.getErrorHandler().genericError(reportErrorsOn, errorMessage);
1409
            }
1410 1411
            return null;
        }
1412

1413 1414 1415
        private boolean checkHasNextFunctionSupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) {
            OverloadResolutionResult hasNextResolutionResult = resolveNoParametersFunction(iteratorType, scope, "hasNext");
            if (hasNextResolutionResult.isAmbiguity()) {
1416
                trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().hasNext()' is ambiguous for this expression");
1417 1418 1419 1420 1421
            } else if (hasNextResolutionResult.isNothing()) {
                return false;
            } else {
                JetType hasNextReturnType = hasNextResolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
                if (!isBoolean(hasNextReturnType)) {
1422
                    trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext()' method of the loop range must return Boolean, but returns " + hasNextReturnType);
1423
                }
1424
            }
1425 1426
            return true;
        }
1427

1428
        private boolean checkHasNextPropertySupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) {
1429
            VariableDescriptor hasNextProperty = iteratorType.getMemberScope().getVariable("hasNext");
1430 1431 1432 1433 1434 1435 1436
            // TODO :extension properties
            if (hasNextProperty == null) {
                return false;
            } else {
                JetType hasNextReturnType = hasNextProperty.getOutType();
                if (hasNextReturnType == null) {
                    // TODO : accessibility
1437
                    trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must be readable");
1438 1439
                }
                else if (!isBoolean(hasNextReturnType)) {
1440
                    trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must return Boolean, but returns " + hasNextReturnType);
1441 1442 1443 1444 1445
                }
            }
            return true;
        }

A
Andrey Breslav 已提交
1446 1447 1448 1449
        @Override
        public void visitNewExpression(JetNewExpression expression) {
            // TODO : type argument inference
            JetTypeReference typeReference = expression.getTypeReference();
1450
            if (typeReference != null) {
1451
                result = checkConstructorCall(scope, typeReference, expression);
1452
            }
A
Andrey Breslav 已提交
1453 1454 1455
        }

        @Override
A
Andrey Breslav 已提交
1456
        public void visitHashQualifiedExpression(JetHashQualifiedExpression expression) {
1457
            trace.getErrorHandler().genericError(expression.getOperationTokenNode(), "Unsupported");
A
Andrey Breslav 已提交
1458 1459 1460 1461
        }

        @Override
        public void visitQualifiedExpression(JetQualifiedExpression expression) {
1462
            // TODO : functions as values
A
Andrey Breslav 已提交
1463
            JetExpression selectorExpression = expression.getSelectorExpression();
1464
            JetExpression receiverExpression = expression.getReceiverExpression();
1465
            JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression);
A
Andrey Breslav 已提交
1466
            if (receiverType != null) {
A
Andrey Breslav 已提交
1467 1468
                JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
                if (expression.getOperationSign() == JetTokens.QUEST) {
1469
                    if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) {
A
Andrey Breslav 已提交
1470
                        // TODO : more comprehensible error message
1471
                        trace.getErrorHandler().typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType);
A
Andrey Breslav 已提交
1472 1473
                    }
                    result = TypeUtils.makeNullable(receiverType);
A
Andrey Breslav 已提交
1474
                }
A
Andrey Breslav 已提交
1475 1476
                else {
                    result = selectorReturnType;
1477
                }
A
Andrey Breslav 已提交
1478 1479 1480
                if (selectorExpression != null && result != null) {
                    trace.recordExpressionType(selectorExpression, result);
                }
1481 1482 1483 1484 1485
                if (selectorReturnType != null) {
                    // TODO : extensions to 'Any?'
                    assert selectorExpression != null;
                    checkNullSafety(receiverType, expression.getOperationTokenNode(), getCalleeFunctionDescriptor(selectorExpression));
                }
A
Andrey Breslav 已提交
1486 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 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
        @NotNull
        private FunctionDescriptor getCalleeFunctionDescriptor(@NotNull JetExpression selectorExpression) {
            final FunctionDescriptor[] result = new FunctionDescriptor[1];
            selectorExpression.accept(new JetVisitor() {
                @Override
                public void visitCallExpression(JetCallExpression callExpression) {
                    callExpression.getCalleeExpression().accept(this);
                }

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

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

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

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

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

1532 1533 1534 1535 1536
        private JetType getCallExpressionType(@Nullable JetType receiverType, @NotNull JetCallExpression callExpression) {
            OverloadDomain overloadDomain = getOverloadDomain(receiverType, scope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
            return resolveCall(scope, overloadDomain, callExpression);
        }

A
Andrey Breslav 已提交
1537 1538
        private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) {
            if (selectorExpression instanceof JetCallExpression) {
1539
                return getCallExpressionType(receiverType, (JetCallExpression) selectorExpression);
A
Andrey Breslav 已提交
1540 1541
            }
            else if (selectorExpression instanceof JetSimpleNameExpression) {
1542
                JetScope compositeScope = new ScopeWithReceiver(scope, receiverType, semanticServices.getTypeChecker());
A
Andrey Breslav 已提交
1543 1544 1545 1546
                return getType(compositeScope, selectorExpression, false);
            }
            else if (selectorExpression != null) {
                // TODO : not a simple name -> resolve in scope, expect property type or a function type
1547
                trace.getErrorHandler().genericError(selectorExpression.getNode(), "Unsupported selector element type: " + selectorExpression);
A
Andrey Breslav 已提交
1548 1549 1550 1551
            }
            return receiverType;
        }

A
Andrey Breslav 已提交
1552 1553
        @Override
        public void visitCallExpression(JetCallExpression expression) {
1554
            result = getCallExpressionType(null, expression);
1555
        }
A
Andrey Breslav 已提交
1556

A
Andrey Breslav 已提交
1557 1558 1559
        @Override
        public void visitIsExpression(JetIsExpression expression) {
            // TODO : patterns and everything
A
Andrey Breslav 已提交
1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570
            JetType knownType = getType(scope, expression.getLeftHandSide(), false);
            JetPattern pattern = expression.getPattern();
            if (pattern instanceof JetTypePattern) {
                JetTypePattern typePattern = (JetTypePattern) pattern;
                JetTypeReference typeReference = typePattern.getTypeReference();
                if (typeReference != null && knownType != null) {
                    JetType targetType = typeResolver.resolveType(scope, typeReference);
                    if (!semanticServices.getTypeChecker().isSubtypeOf(targetType, knownType)) {
                        trace.getErrorHandler().genericWarning(expression.getNode(), "Expression always evaluates to false"); // TODO : make an error?
                    }
                }
1571 1572 1573
            }
            else {
                trace.getErrorHandler().genericError(pattern.getNode(), "Unsupported [JetTypeInferrer]");
A
Andrey Breslav 已提交
1574
            }
A
Andrey Breslav 已提交
1575 1576 1577
            result = semanticServices.getStandardLibrary().getBooleanType();
        }

A
Andrey Breslav 已提交
1578
        @Override
1579
        public void visitUnaryExpression(JetUnaryExpression expression) {
A
Andrey Breslav 已提交
1580
            JetSimpleNameExpression operationSign = expression.getOperationSign();
1581 1582 1583 1584 1585
            if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
                // TODO : Some processing for the label?
                result = getType(expression.getBaseExpression());
                return;
            }
A
Andrey Breslav 已提交
1586 1587
            IElementType operationType = operationSign.getReferencedNameElementType();
            String name = unaryOperationNames.get(operationType);
1588
            if (name == null) {
1589
                trace.getErrorHandler().genericError(operationSign.getNode(), "Unknown unary operation");
1590 1591
            }
            else {
A
Andrey Breslav 已提交
1592 1593 1594
                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 已提交
1595
                    if (functionDescriptor != null) {
A
Andrey Breslav 已提交
1596 1597
                        JetType returnType = functionDescriptor.getUnsubstitutedReturnType();
                        if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
1598 1599 1600 1601 1602
                            if (semanticServices.getTypeChecker().isSubtypeOf(returnType, JetStandardClasses.getUnitType())) {
                                 result = JetStandardClasses.getUnitType();
                            }
                            else {
                                if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) {
1603
                                    trace.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType);
1604 1605 1606
                                }
                                // TODO : Maybe returnType?
                                result = receiverType;
A
Andrey Breslav 已提交
1607 1608 1609 1610
                            }
                        } else {
                            result = returnType;
                        }
A
Andrey Breslav 已提交
1611 1612 1613 1614 1615 1616 1617 1618 1619
                    }
                }
            }
        }

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

A
Andrey Breslav 已提交
1620 1621 1622
            JetExpression left = expression.getLeft();
            JetExpression right = expression.getRight();

A
Andrey Breslav 已提交
1623 1624
            IElementType operationType = operationSign.getReferencedNameElementType();
            if (operationType == JetTokens.IDENTIFIER) {
1625 1626 1627 1628
                String referencedName = operationSign.getReferencedName();
                if (referencedName != null) {
                    result = getTypeForBinaryCall(expression, referencedName, scope, true);
                }
A
Andrey Breslav 已提交
1629
            }
1630
            else if (binaryOperationNames.containsKey(operationType)) {
A
Andrey Breslav 已提交
1631
                result = getTypeForBinaryCall(expression, binaryOperationNames.get(operationType), scope, true);
A
Andrey Breslav 已提交
1632 1633
            }
            else if (operationType == JetTokens.EQ) {
A
Andrey Breslav 已提交
1634 1635 1636 1637
                visitAssignment(expression);
            }
            else if (assignmentOperationNames.containsKey(operationType)) {
                visitAssignmentOperation(expression);
A
Andrey Breslav 已提交
1638
            }
1639
            else if (comparisonOperations.contains(operationType)) {
A
Andrey Breslav 已提交
1640
                JetType compareToReturnType = getTypeForBinaryCall(expression, "compareTo", scope, true);
A
Andrey Breslav 已提交
1641 1642 1643 1644 1645 1646 1647
                if (compareToReturnType != null) {
                    TypeConstructor constructor = compareToReturnType.getConstructor();
                    JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
                    TypeConstructor intTypeConstructor = standardLibrary.getInt().getTypeConstructor();
                    if (constructor.equals(intTypeConstructor)) {
                        result = standardLibrary.getBooleanType();
                    } else {
1648
                        trace.getErrorHandler().genericError(operationSign.getNode(), "compareTo must return Int, but returns " + compareToReturnType);
A
Andrey Breslav 已提交
1649
                    }
A
Andrey Breslav 已提交
1650
                }
A
Andrey Breslav 已提交
1651
            }
A
Equals  
Andrey Breslav 已提交
1652
            else if (equalsOperations.contains(operationType)) {
A
Andrey Breslav 已提交
1653
                String name = "equals";
1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667
                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 {
1668
                                trace.getErrorHandler().genericError(operationSign.getNode(), "No method 'equals(Any?) : Boolean' available");
1669 1670 1671 1672 1673
                            }
                        }
                    }
                }
                result = semanticServices.getStandardLibrary().getBooleanType();
1674 1675 1676 1677 1678 1679
            }
            else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
                ensureNonemptyIntersectionOfOperandTypes(expression);

                // TODO : Check comparison pointlessness
                result = semanticServices.getStandardLibrary().getBooleanType();
A
Andrey Breslav 已提交
1680 1681 1682
            }
            else if (inOperations.contains(operationType)) {
                if (right == null) {
A
rename  
Andrey Breslav 已提交
1683
                    result = ErrorUtils.createErrorType("No right argument"); // TODO
A
Andrey Breslav 已提交
1684
                    return;
A
Andrey Breslav 已提交
1685
                }
1686
                checkInExpression(operationSign, left, right);
1687
                result = semanticServices.getStandardLibrary().getBooleanType();
A
Equals  
Andrey Breslav 已提交
1688
            }
A
Andrey Breslav 已提交
1689 1690 1691 1692
            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)) {
1693
                    trace.getErrorHandler().typeMismatch(left, semanticServices.getStandardLibrary().getBooleanType(), leftType);
A
Andrey Breslav 已提交
1694 1695
                }
                if (rightType != null && !isBoolean(rightType)) {
1696
                    trace.getErrorHandler().typeMismatch(right, semanticServices.getStandardLibrary().getBooleanType(), rightType);
A
Andrey Breslav 已提交
1697 1698 1699
                }
                result = semanticServices.getStandardLibrary().getBooleanType();
            }
A
Andrey Breslav 已提交
1700 1701 1702 1703 1704
            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()) {
1705
                        trace.getErrorHandler().genericWarning(left.getNode(), "Elvis operator (?:) is always returns the left operand of non-nullable type " + leftType);
A
Andrey Breslav 已提交
1706 1707 1708 1709 1710 1711
                    }
                    if (rightType != null) {
                        result = TypeUtils.makeNullableAsSpecified(semanticServices.getTypeChecker().commonSupertype(leftType, rightType), rightType.isNullable());
                    }
                }
            }
A
Equals  
Andrey Breslav 已提交
1712
            else {
1713
                trace.getErrorHandler().genericError(operationSign.getNode(), "Unknown operation");
A
Andrey Breslav 已提交
1714 1715 1716
            }
        }

1717 1718 1719 1720 1721 1722
        private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right) {
            String name = "contains";
            JetType containsType = getTypeForBinaryCall(scope, right, operationSign, left, name, true);
            ensureBooleanResult(operationSign, name, containsType);
        }

1723 1724 1725 1726 1727 1728 1729
        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);
1730
            if (leftType != null && right != null) {
1731 1732
                JetType rightType = getType(scope, right, false);

1733 1734 1735
                if (rightType != null) {
                    JetType intersect = TypeUtils.intersect(semanticServices.getTypeChecker(), new HashSet<JetType>(Arrays.asList(leftType, rightType)));
                    if (intersect == null) {
1736
                        trace.getErrorHandler().genericError(expression.getNode(), "Operator " + operationSign.getReferencedName() + " cannot be applied to " + leftType + " and " + rightType);
1737
                    }
1738 1739 1740 1741
                }
            }
        }

A
Andrey Breslav 已提交
1742 1743 1744 1745 1746 1747 1748 1749 1750
        protected void visitAssignmentOperation(JetBinaryExpression expression) {
            assignmentIsNotAnExpressionError(expression);
        }

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

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

1754 1755 1756 1757 1758
        private boolean ensureBooleanResult(JetExpression operationSign, String name, JetType resultType) {
            return ensureBooleanResultWithCustomSubject(operationSign, resultType, "'" + name + "'");
        }

        private boolean ensureBooleanResultWithCustomSubject(JetExpression operationSign, JetType resultType, String subjectName) {
A
Andrey Breslav 已提交
1759 1760
            if (resultType != null) {
                // TODO : Relax?
A
Andrey Breslav 已提交
1761
                if (!isBoolean(resultType)) {
1762
                    trace.getErrorHandler().genericError(operationSign.getNode(), subjectName + " must return Boolean but returns " + resultType);
1763
                    return false;
A
Andrey Breslav 已提交
1764 1765
                }
            }
1766
            return true;
A
Andrey Breslav 已提交
1767 1768
        }

A
Andrey Breslav 已提交
1769
        private boolean isBoolean(@NotNull JetType type) {
A
Andrey Breslav 已提交
1770
            return semanticServices.getTypeChecker().isConvertibleTo(type,  semanticServices.getStandardLibrary().getBooleanType());
A
Andrey Breslav 已提交
1771 1772
        }

A
Andrey Breslav 已提交
1773 1774 1775 1776 1777 1778 1779 1780
        @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;

1781 1782 1783 1784 1785
            if (receiverType != null) {
                FunctionDescriptor functionDescriptor = lookupFunction(scope, expression, "get", receiverType, argumentTypes, true);
                if (functionDescriptor != null) {
                    result = functionDescriptor.getUnsubstitutedReturnType();
                }
A
Andrey Breslav 已提交
1786 1787 1788
            }
        }

1789
        @Nullable
1790 1791 1792 1793 1794
        protected JetType getTypeForBinaryCall(
                @NotNull JetBinaryExpression expression,
                @NotNull String name,
                @NotNull JetScope scope,
                boolean reportUnresolved) {
A
Andrey Breslav 已提交
1795 1796 1797
            JetExpression left = expression.getLeft();
            JetExpression right = expression.getRight();
            if (right == null) {
1798
                return null;
A
Andrey Breslav 已提交
1799
            }
A
Andrey Breslav 已提交
1800 1801 1802 1803
            JetSimpleNameExpression operationSign = expression.getOperationReference();
            return getTypeForBinaryCall(scope, left, operationSign, right, name, reportUnresolved);
        }

1804
        @Nullable
1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
        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) {
1815 1816
                return null;
            }
A
Andrey Breslav 已提交
1817
            FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType), reportUnresolved);
A
Andrey Breslav 已提交
1818
            if (functionDescriptor != null) {
1819 1820
                if (leftType.isNullable()) {
                    // TODO : better error message for '1 + nullableVar' case
1821
                    trace.getErrorHandler().genericError(operationSign.getNode(),
1822 1823 1824 1825 1826 1827
                            "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 已提交
1828 1829 1830 1831
                return functionDescriptor.getUnsubstitutedReturnType();
            }
            return null;
        }
A
Andrey Breslav 已提交
1832 1833 1834

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

1838 1839
        @Override
        public void visitRootNamespaceExpression(JetRootNamespaceExpression expression) {
1840
            trace.getErrorHandler().genericError(expression.getNode(), "'namespace' is not an expression");
1841 1842 1843
            result = null;
        }

A
Andrey Breslav 已提交
1844
        @Override
1845 1846
        public void visitJetElement(JetElement element) {
            trace.getErrorHandler().genericError(element.getNode(), "[JetTypeInferrer] Unsupported element: " + element + " " + element.getClass().getCanonicalName());
A
Andrey Breslav 已提交
1847 1848 1849
        }
    }

1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
    private class TypeInferrerVisitorWithNamespaces extends TypeInferrerVisitor {
        private TypeInferrerVisitorWithNamespaces(@NotNull JetScope scope, boolean preferBlock) {
            super(scope, preferBlock);
        }

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

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

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

    }

A
Andrey Breslav 已提交
1874 1875 1876
    private class TypeInferrerVisitorWithWritableScope extends TypeInferrerVisitor {
        private final WritableScope scope;

1877 1878
        public TypeInferrerVisitorWithWritableScope(@NotNull WritableScope scope, boolean preferBlock) {
            super(scope, preferBlock);
A
Andrey Breslav 已提交
1879 1880 1881
            this.scope = scope;
        }

A
Andrey Breslav 已提交
1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
        @Override
        public void visitObjectDeclaration(JetObjectDeclaration declaration) {
            TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, trace);
            topDownAnalyzer.processObject(scope, scope.getContainingDeclaration(), declaration);
            ClassDescriptor classDescriptor = trace.getBindingContext().getClassDescriptor(declaration);
            if (classDescriptor != null) {
                PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolveObjectDeclarationAsPropertyDescriptor(scope.getContainingDeclaration(), declaration, classDescriptor);
                scope.addVariableDescriptor(propertyDescriptor);
            }
        }

A
Andrey Breslav 已提交
1893 1894
        @Override
        public void visitProperty(JetProperty property) {
1895

1896 1897 1898 1899 1900
            JetTypeReference receiverTypeRef = property.getReceiverTypeRef();
            if (receiverTypeRef != null) {
                trace.getErrorHandler().genericError(receiverTypeRef.getNode(), "Local receiver-properties are not allowed");
            }

1901 1902
            JetPropertyAccessor getter = property.getGetter();
            if (getter != null) {
1903
                trace.getErrorHandler().genericError(getter.getNode(), "Local variables are not allowed to have getters");
1904 1905 1906 1907
            }

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

1911
            VariableDescriptor propertyDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, property);
1912 1913 1914 1915 1916 1917 1918
            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)) {
1919
                    trace.getErrorHandler().typeMismatch(initializer, outType, initializerType);
1920 1921 1922
                }
            }

1923
            scope.addVariableDescriptor(propertyDescriptor);
A
Andrey Breslav 已提交
1924 1925 1926 1927
        }

        @Override
        public void visitFunction(JetFunction function) {
1928
            scope.addFunctionDescriptor(classDescriptorResolver.resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function));
A
Andrey Breslav 已提交
1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960
        }

        @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);
            }
1961
            result = null; // not an expression
A
Andrey Breslav 已提交
1962 1963 1964 1965 1966
        }

        @Override
        protected void visitAssignment(JetBinaryExpression expression) {
            JetExpression left = expression.getLeft();
1967
            JetExpression deparenthesized = JetPsiUtil.deparenthesize(left);
A
Andrey Breslav 已提交
1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979
            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)) {
1980
                        trace.getErrorHandler().typeMismatch(right, leftType, rightType);
A
Andrey Breslav 已提交
1981 1982 1983
                    }
                }
            }
A
Andrey Breslav 已提交
1984
            result = null; // This is not an element
A
Andrey Breslav 已提交
1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005
        }

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

A
Andrey Breslav 已提交
2010
    }
A
Andrey Breslav 已提交
2011

2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023
//    private class CachedBindingTrace extends BindingTraceAdapter {
//
//        public CachedBindingTrace(BindingTrace originalTrace) {
//            super(originalTrace);
//        }
//
//        @Override
//        public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) {
//            super.recordExpressionType(expression, type);
//            typeCache.put(expression, type);
//        }
//    }
2024
}