JetTypeInferrer.java 29.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
package org.jetbrains.jet.lang.types;

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;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lexer.JetTokens;

import java.util.*;

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

    private final BindingTrace trace;
    private final JetSemanticServices semanticServices;
A
Andrey Breslav 已提交
21 22
    private final TypeResolver typeResolver;
    private final ClassDescriptorResolver classDescriptorResolver;
23 24 25 26

    public JetTypeInferrer(BindingTrace trace, JetSemanticServices semanticServices) {
        this.trace = trace;
        this.semanticServices = semanticServices;
A
Andrey Breslav 已提交
27
        this.typeResolver = new TypeResolver(trace, semanticServices);
A
Andrey Breslav 已提交
28
        this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, trace);
29 30
    }

31
    @NotNull
A
Andrey Breslav 已提交
32 33
    public JetType safeGetType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
        JetType type = getType(scope, expression, preferBlock);
34 35 36 37 38
        if (type != null) {
            return type;
        }
        return ErrorType.createErrorType("Type for " + expression.getText());
    }
39

40
    @Nullable
A
Andrey Breslav 已提交
41 42
    public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
        final JetType[] result = new JetType[1];
43 44
        expression.accept(new JetVisitor() {
            @Override
45
            public void visitReferenceExpression(JetSimpleNameExpression expression) {
46 47
                // TODO : other members
                // TODO : type substitutions???
48 49
                String referencedName = expression.getReferencedName();
                PropertyDescriptor property = scope.getProperty(referencedName);
50
                if (property != null) {
51
                    trace.recordReferenceResolution(expression, property);
52
                    result[0] = property.getType();
53
                    return;
54
                } else {
55 56 57 58 59 60
                    NamespaceDescriptor namespace = scope.getNamespace(referencedName);
                    if (namespace != null) {
                        trace.recordReferenceResolution(expression, namespace);
                        result[0] = namespace.getNamespaceType();
                        return;
                    }
61
                }
62
                semanticServices.getErrorHandler().unresolvedReference(expression);
63 64 65 66 67 68 69 70 71
            }

            @Override
            public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
                if (preferBlock && !expression.hasParameterSpecification()) {
                    result[0] = getBlockReturnedType(scope, expression.getBody());
                    return;
                }

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

74 75 76
                JetTypeReference returnTypeRef = expression.getReturnTypeRef();

                JetTypeReference receiverTypeRef = expression.getReceiverTypeRef();
A
Andrey Breslav 已提交
77
                final JetType receiverType;
78
                if (receiverTypeRef != null) {
A
Andrey Breslav 已提交
79
                    receiverType = typeResolver.resolveType(scope, receiverTypeRef);
80 81 82 83 84 85
                } else {
                    receiverType = scope.getThisType();
                }

                List<JetElement> body = expression.getBody();
                final Map<String, PropertyDescriptor> parameterDescriptors = new HashMap<String, PropertyDescriptor>();
A
Andrey Breslav 已提交
86
                List<JetType> parameterTypes = new ArrayList<JetType>();
87 88 89 90 91
                for (JetParameter parameter : expression.getParameters()) {
                    JetTypeReference typeReference = parameter.getTypeReference();
                    if (typeReference == null) {
                        throw new UnsupportedOperationException("Type inference for parameters is not implemented yet");
                    }
92
                    PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolvePropertyDescriptor(functionDescriptor, scope, parameter);
93 94 95
                    parameterDescriptors.put(parameter.getName(), propertyDescriptor);
                    parameterTypes.add(propertyDescriptor.getType());
                }
A
Andrey Breslav 已提交
96
                JetType returnType;
97
                if (returnTypeRef != null) {
A
Andrey Breslav 已提交
98
                    returnType = typeResolver.resolveType(scope, returnTypeRef);
99
                } else {
100
                    WritableScope writableScope = new WritableScope(scope, functionDescriptor);
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
                    for (PropertyDescriptor propertyDescriptor : parameterDescriptors.values()) {
                        writableScope.addPropertyDescriptor(propertyDescriptor);
                    }
                    writableScope.setThisType(receiverType);
                    returnType = getBlockReturnedType(writableScope, body);
                }
                result[0] = JetStandardClasses.getFunctionType(null, receiverTypeRef == null ? null : receiverType, parameterTypes, returnType);
            }

            @Override
            public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
                result[0] = getType(scope, expression.getExpression(), false);
            }

            @Override
            public void visitConstantExpression(JetConstantExpression expression) {
                IElementType elementType = expression.getNode().getElementType();
                JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary();
                if (elementType == JetNodeTypes.INTEGER_CONSTANT) {
                    result[0] = standardLibrary.getIntType();
                } else if (elementType == JetNodeTypes.LONG_CONSTANT) {
                    result[0] = standardLibrary.getLongType();
                } else if (elementType == JetNodeTypes.FLOAT_CONSTANT) {
                    String text = expression.getText();
                    assert text.length() > 0;
                    char lastChar = text.charAt(text.length() - 1);
                    if (lastChar == 'f' || lastChar == 'F') {
                        result[0] = standardLibrary.getFloatType();
                    } else {
                        result[0] = standardLibrary.getDoubleType();
                    }
                } else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) {
                    result[0] = standardLibrary.getBooleanType();
                } else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) {
                    result[0] = standardLibrary.getCharType();
                } else if (elementType == JetNodeTypes.STRING_CONSTANT) {
                    result[0] = standardLibrary.getStringType();
                } else if (elementType == JetNodeTypes.NULL) {
                    result[0] = JetStandardClasses.getNullableNothingType();
                } else {
                    throw new IllegalArgumentException("Unsupported constant: " + expression);
                }
            }

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

            @Override
            public void visitReturnExpression(JetReturnExpression expression) {
152 153 154 155
                JetExpression returnedExpression = expression.getReturnedExpression();
                if (returnedExpression != null) {
                    getType(scope, returnedExpression, false);
                }
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
                result[0] = JetStandardClasses.getNothingType();
            }

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

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

            @Override
            public void visitTypeofExpression(JetTypeofExpression expression) {
                throw new UnsupportedOperationException("Return some reflection interface"); // TODO
            }

            @Override
            public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) {
176
                if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.COLON) {
A
Andrey Breslav 已提交
177 178
                    JetType actualType = getType(scope, expression.getLeft(), false);
                    JetType expectedType = typeResolver.resolveType(scope, expression.getRight());
179
                    if (actualType != null && !semanticServices.getTypeChecker().isSubtypeOf(actualType, expectedType)) {
180 181
                        // TODO
                        semanticServices.getErrorHandler().typeMismatch(expression.getLeft(), expectedType, actualType);
182
                    }
183 184
                    result[0] = expectedType;
                    return;
185 186 187 188 189 190 191 192 193 194 195 196 197
                }
                throw new UnsupportedOperationException(); // TODO
            }

            @Override
            public void visitIfExpression(JetIfExpression expression) {
                // TODO : check condition type
                // TODO : change types according to is and nullability checks
                JetExpression elseBranch = expression.getElse();
                if (elseBranch == null) {
                    // TODO : type-check the branch
                    result[0] = JetStandardClasses.getUnitType();
                } else {
A
Andrey Breslav 已提交
198 199
                    JetType thenType = getType(scope, expression.getThen(), true);
                    JetType elseType = getType(scope, elseBranch, true);
200
                    result[0] = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
201 202 203 204 205 206
                }
            }

            @Override
            public void visitWhenExpression(JetWhenExpression expression) {
                // TODO :change scope according to the bound value in the when header
A
Andrey Breslav 已提交
207
                List<JetType> expressions = new ArrayList<JetType>();
208
                collectAllReturnTypes(expression, scope, expressions);
209
                result[0] = semanticServices.getTypeChecker().commonSupertype(expressions);
210 211 212 213 214 215 216
            }

            @Override
            public void visitTryExpression(JetTryExpression expression) {
                JetExpression tryBlock = expression.getTryBlock();
                List<JetCatchClause> catchClauses = expression.getCatchClauses();
                JetFinallySection finallyBlock = expression.getFinallyBlock();
A
Andrey Breslav 已提交
217
                List<JetType> types = new ArrayList<JetType>();
218 219 220 221 222 223 224 225 226
                if (finallyBlock == null) {
                    for (JetCatchClause catchClause : catchClauses) {
                        // TODO: change scope here
                        types.add(getType(scope, catchClause.getCatchBody(), true));
                    }
                } else {
                    types.add(getType(scope, finallyBlock.getFinalExpression(), true));
                }
                types.add(getType(scope, tryBlock, true));
227
                result[0] = semanticServices.getTypeChecker().commonSupertype(types);
228 229 230 231 232
            }

            @Override
            public void visitTupleExpression(JetTupleExpression expression) {
                List<JetExpression> entries = expression.getEntries();
A
Andrey Breslav 已提交
233
                List<JetType> types = new ArrayList<JetType>();
234 235 236 237 238 239 240 241 242 243
                for (JetExpression entry : entries) {
                    types.add(getType(scope, entry, false));
                }
                // TODO : labels
                result[0] = JetStandardClasses.getTupleType(types);
            }

            @Override
            public void visitThisExpression(JetThisExpression expression) {
                // TODO : qualified this, e.g. Foo.this<Bar>
A
Andrey Breslav 已提交
244
                JetType thisType = scope.getThisType();
245 246 247 248
                JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier();
                if (superTypeQualifier != null) {
                    // This cast must be safe (assuming the PSI doesn't contain errors)
                    JetUserType typeElement = (JetUserType) superTypeQualifier.getTypeElement();
A
Andrey Breslav 已提交
249
                    ClassDescriptor superclass = typeResolver.resolveClass(scope, typeElement);
A
Andrey Breslav 已提交
250
                    Collection<? extends JetType> supertypes = thisType.getConstructor().getSupertypes();
251
                    Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.getSubstitutionContext(thisType);
A
Andrey Breslav 已提交
252
                    for (JetType declaredSupertype : supertypes) {
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
                        if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
                            result[0] = TypeSubstitutor.INSTANCE.substitute(substitutionContext, declaredSupertype, Variance.INVARIANT);
                            break;
                        }
                    }
                    assert result[0] != null;
                } else {
                    result[0] = thisType;
                }
            }

            @Override
            public void visitBlockExpression(JetBlockExpression expression) {
                result[0] = getBlockReturnedType(scope, expression.getStatements());
            }

            @Override
            public void visitLoopExpression(JetLoopExpression expression) {
                result[0] = JetStandardClasses.getUnitType();
            }

            @Override
            public void visitNewExpression(JetNewExpression expression) {
                // TODO : type argument inference
                JetTypeReference typeReference = expression.getTypeReference();
A
Andrey Breslav 已提交
278
                result[0] = typeResolver.resolveType(scope, typeReference);
279 280 281 282 283 284 285
            }

            @Override
            public void visitDotQualifiedExpression(JetDotQualifiedExpression expression) {
                // TODO : functions
                JetExpression receiverExpression = expression.getReceiverExpression();
                JetExpression selectorExpression = expression.getSelectorExpression();
A
Andrey Breslav 已提交
286
                JetType receiverType = getType(scope, receiverExpression, false);
287 288 289 290
                if (receiverType != null) { // TODO : review
                    JetScope compositeScope = new ScopeWithReceiver(scope, receiverType);
                    result[0] = getType(compositeScope, selectorExpression, false);
                }
291 292 293 294 295 296 297 298 299 300 301 302 303
            }

            @Override
            public void visitCallExpression(JetCallExpression expression) {
                JetExpression calleeExpression = expression.getCalleeExpression();

                // 1) ends with a name -> (scope, name) to look up
                // 2) ends with something else -> just check types

                // TODO : check somewhere that these are NOT projections
                List<JetTypeProjection> typeArguments = expression.getTypeArguments();

                List<JetArgument> valueArguments = expression.getValueArguments();
A
Andrey Breslav 已提交
304

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
                boolean someNamed = false;
                for (JetArgument argument : valueArguments) {
                    if (argument.isNamed()) {
                        someNamed = true;
                        break;
                    }
                }
                List<JetExpression> functionLiteralArguments = expression.getFunctionLiteralArguments();

//                JetExpression functionLiteralArgument = functionLiteralArguments.isEmpty() ? null : functionLiteralArguments.get(0);
                // TODO : must be a check
                assert functionLiteralArguments.size() <= 1;

                OverloadDomain overloadDomain = getOverloadDomain(scope, calleeExpression);
                if (someNamed) {
                    // TODO : check that all are named
                    throw new UnsupportedOperationException(); // TODO

//                    result[0] = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArguments, functionLiteralArgument);
                } else {
A
Andrey Breslav 已提交
325
                    List<JetType> types = new ArrayList<JetType>();
326 327 328 329 330
                    for (JetTypeProjection projection : typeArguments) {
                        // TODO : check that there's no projection
                        types.add(typeResolver.resolveType(scope, projection.getTypeReference()));
                    }

331 332 333 334 335 336 337
                    List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
                    for (JetArgument argument : valueArguments) {
                        positionedValueArguments.add(argument.getArgumentExpression());
                    }

                    positionedValueArguments.addAll(functionLiteralArguments);

A
Andrey Breslav 已提交
338
                    List<JetType> valueArgumentTypes = new ArrayList<JetType>();
339 340 341 342 343 344 345 346 347 348 349
                    for (JetExpression valueArgument : positionedValueArguments) {
                        valueArgumentTypes.add(getType(scope, valueArgument, false));
                    }

                    FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
                    if (functionDescriptor != null) {
                        result[0] = functionDescriptor.getUnsubstitutedReturnType();
                    }
                }
            }

350 351
            @Override
            public void visitBinaryExpression(JetBinaryExpression expression) {
352
                JetSimpleNameExpression operationSign = expression.getOperationReference();
353 354 355 356 357 358 359

                IElementType operationType = operationSign.getReferencedNameElementType();
                if (operationType == JetTokens.IDENTIFIER) {
                    result[0] = getTypeForBinaryCall(expression, operationSign.getReferencedName(), scope);
                }
                else if (operationType == JetTokens.PLUS) {
                    result[0] = getTypeForBinaryCall(expression, "plus", scope);
360 361 362
                }
                else if (operationType == JetTokens.EQ) {
                    JetExpression left = expression.getLeft();
363 364 365
                    JetExpression deparenthesized = deparenthesize(left);
                    if (deparenthesized instanceof JetArrayAccessExpression) {
                        JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) deparenthesized;
366 367 368
                        resolveArrayAccessToLValue(arrayAccessExpression, expression.getRight(), expression.getOperationReference());
                    }
                    else {
A
Andrey Breslav 已提交
369 370
                        getType(scope, expression.getRight(), false);
                        //throw new UnsupportedOperationException();
371 372
                    }
                    result[0] = null; // TODO : This is not an expression, in fact!
373 374 375 376 377
                } else {
                    throw new UnsupportedOperationException(); // TODO
                }
            }

378 379 380
            @Override
            public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
                JetExpression arrayExpression = expression.getArrayExpression();
A
Andrey Breslav 已提交
381
                JetType receiverType = getType(scope, arrayExpression, false);
382
                List<JetExpression> indexExpressions = expression.getIndexExpressions();
A
Andrey Breslav 已提交
383
                List<JetType> argumentTypes = getTypes(scope, indexExpressions);
384 385
                if (argumentTypes == null) return;

386
                FunctionDescriptor functionDescriptor = lookupFunction(scope, expression, "get", receiverType, argumentTypes);
387 388 389 390 391
                if (functionDescriptor != null) {
                    result[0] = functionDescriptor.getUnsubstitutedReturnType();
                }
            }

392
            private void resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign) {
A
Andrey Breslav 已提交
393
                List<JetType> argumentTypes = getTypes(scope, arrayAccessExpression.getIndexExpressions());
394
                if (argumentTypes == null) return;
A
Andrey Breslav 已提交
395
                JetType rhsType = getType(scope, rightHandSide, false);
396 397 398
                if (rhsType == null) return;
                argumentTypes.add(rhsType);

A
Andrey Breslav 已提交
399
                JetType receiverType = getType(scope, arrayAccessExpression.getArrayExpression(), false);
400 401
                if (receiverType == null) return;

402 403
                // TODO : nasty hack: effort is duplicated
                lookupFunction(scope, arrayAccessExpression, "set", receiverType, argumentTypes);
404 405 406 407 408 409
                FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, "set", receiverType, argumentTypes);
                if (functionDescriptor != null) {
                    result[0] = functionDescriptor.getUnsubstitutedReturnType();
                }
            }

410 411 412 413
            @Override
            public void visitJetElement(JetElement elem) {
                throw new IllegalArgumentException("Unsupported element: " + elem);
            }
414

A
Andrey Breslav 已提交
415
            private JetType getTypeForBinaryCall(JetBinaryExpression expression, String name, JetScope scope) {
416
                JetSimpleNameExpression operationSign = expression.getOperationReference();
417
                JetExpression left = expression.getLeft();
A
Andrey Breslav 已提交
418
                JetType leftType = getType(scope, left, false);
419
                JetExpression right = expression.getRight();
420 421 422
                if (right == null) {
                    return ErrorType.createErrorType("No right argument");
                }
A
Andrey Breslav 已提交
423
                JetType rightType = getType(scope, right, false);
424
                FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType));
425 426 427 428 429
                if (functionDescriptor != null) {
                    return functionDescriptor.getUnsubstitutedReturnType();
                }
                return null;
            }
430
        });
A
Andrey Breslav 已提交
431 432 433
        if (result[0] != null) {
            trace.recordExpressionType(expression, result[0]);
        }
434 435 436
        return result[0];
    }

437 438 439 440 441 442 443 444
    @NotNull
    private JetExpression deparenthesize(@NotNull JetExpression expression) {
        while (expression instanceof JetParenthesizedExpression) {
            expression = ((JetParenthesizedExpression) expression).getExpression();
        }
        return expression;
    }

445
    @Nullable
A
Andrey Breslav 已提交
446
    private FunctionDescriptor lookupFunction(JetScope scope, JetReferenceExpression reference, String name, JetType receiverType, List<JetType> argumentTypes) {
447 448
        OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name);
        overloadDomain = wrapForTracing(overloadDomain, reference);
A
Andrey Breslav 已提交
449
        return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<JetType>emptyList(), argumentTypes);
450 451 452
    }

    @Nullable
A
Andrey Breslav 已提交
453 454
    private List<JetType> getTypes(JetScope scope, List<JetExpression> indexExpressions) {
        List<JetType> argumentTypes = new ArrayList<JetType>();
455
        for (JetExpression indexExpression : indexExpressions) {
A
Andrey Breslav 已提交
456
            JetType type = getType(scope, indexExpression, false);
457 458 459 460 461 462 463 464
            if (type == null) {
                return null;
            }
            argumentTypes.add(type);
        }
        return argumentTypes;
    }

465

466 467
    private OverloadDomain getOverloadDomain(final JetScope scope, JetExpression calleeExpression) {
        final OverloadDomain[] result = new OverloadDomain[1];
468
        final JetSimpleNameExpression[] reference = new JetSimpleNameExpression[1];
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
        calleeExpression.accept(new JetVisitor() {

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

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

            @Override
            public void visitQualifiedExpression(JetQualifiedExpression expression) {
                // . or ?.
                JetExpression selectorExpression = expression.getSelectorExpression();
487 488
                if (selectorExpression instanceof JetSimpleNameExpression) {
                    JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression;
489

A
Andrey Breslav 已提交
490
                    JetType receiverType = getType(scope, expression.getReceiverExpression(), false);
491
                    if (receiverType != null) {
492
                        result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referenceExpression.getReferencedName());
493 494
                        reference[0] = referenceExpression;
                    }
495 496 497 498 499 500
                } else {
                    throw new UnsupportedOperationException(); // TODO
                }
            }

            @Override
501
            public void visitReferenceExpression(JetSimpleNameExpression expression) {
502
                // a -- create a hierarchical lookup domain for this.a
503
                result[0] = semanticServices.getOverloadResolver().getOverloadDomain(null, scope, expression.getReferencedName());
504 505 506 507 508 509 510 511 512 513 514 515 516 517
                reference[0] = expression;
            }

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

            @Override
            public void visitJetElement(JetElement elem) {
                throw new IllegalArgumentException("Unsupported element: " + elem);
            }
        });
518 519 520
        return wrapForTracing(result[0], reference[0]);
    }

521
    private OverloadDomain wrapForTracing(final OverloadDomain overloadDomain, @NotNull final JetReferenceExpression referenceExpression) {
522
        if (overloadDomain == null) return OverloadDomain.EMPTY;
523 524
        return new OverloadDomain() {
            @Override
A
Andrey Breslav 已提交
525
            public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
526
                FunctionDescriptor descriptor = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType);
A
Andrey Breslav 已提交
527
                if (descriptor != null) {
528
                    trace.recordReferenceResolution(referenceExpression, descriptor);
529
                } else {
530
                    semanticServices.getErrorHandler().unresolvedReference(referenceExpression);
A
Andrey Breslav 已提交
531
                }
532 533 534 535
                return descriptor;
            }

            @Override
A
Andrey Breslav 已提交
536
            public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
537
                FunctionDescriptor descriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes);
A
Andrey Breslav 已提交
538
                if (descriptor != null) {
A
Andrey Breslav 已提交
539
                    trace.recordReferenceResolution(referenceExpression, descriptor);
540
                } else {
A
Andrey Breslav 已提交
541
                    semanticServices.getErrorHandler().unresolvedReference(referenceExpression);
A
Andrey Breslav 已提交
542
                }
543 544 545 546 547
                return descriptor;
            }
        };
    }

A
Andrey Breslav 已提交
548
    private JetType getBlockReturnedType(@NotNull JetScope outerScope, List<JetElement> block) {
549 550 551
        if (block.isEmpty()) {
            return JetStandardClasses.getUnitType();
        } else {
552 553
            DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration();
            WritableScope scope = new WritableScope(outerScope, containingDescriptor);
554 555 556 557
            for (JetElement statement : block) {
                // TODO: consider other declarations
                if (statement instanceof JetProperty) {
                    JetProperty property = (JetProperty) statement;
558
                    PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolvePropertyDescriptor(containingDescriptor, scope, property);
559 560
                    scope.addPropertyDescriptor(propertyDescriptor);
                    trace.recordDeclarationResolution(property, propertyDescriptor);
561
                }
A
Andrey Breslav 已提交
562 563 564 565 566 567
                else if (statement instanceof JetExpression) {
                    getType(scope, (JetExpression) statement, true);
                }
                else {
                    throw new UnsupportedOperationException(); // TODO
                }
568 569 570 571 572 573 574
            }
            JetElement lastElement = block.get(block.size() - 1);
            if (lastElement instanceof JetExpression) {
                JetExpression expression = (JetExpression) lastElement;
                return getType(scope, expression, true);
            }
            // TODO: functions, classes, etc.
575
            throw new IllegalArgumentException("Last item in the block must be an expression, but was " + lastElement.getClass().getCanonicalName());
576 577 578
        }
    }

A
Andrey Breslav 已提交
579
    private void collectAllReturnTypes(JetWhenExpression whenExpression, JetScope scope, List<JetType> result) {
580 581 582 583 584 585 586 587 588 589 590 591 592 593
        for (JetWhenEntry entry : whenExpression.getEntries()) {
            JetWhenExpression subWhen = entry.getSubWhen();
            if (subWhen != null) {
                collectAllReturnTypes(subWhen, scope, result);
            } else {
                JetExpression resultExpression = entry.getExpression();
                if (resultExpression != null) {
                    result.add(getType(scope, resultExpression, true));
                }
            }
        }
    }

}