TopDown resolve for functions

This commit is contained in:
Andrey Breslav
2011-02-28 15:09:32 +03:00
parent 4e0b6deda5
commit a532b6db11
11 changed files with 94 additions and 26 deletions
@@ -131,6 +131,7 @@ public class ClassDescriptorResolver {
return new FunctionDescriptorImpl(
function,
null,
AttributeResolver.INSTANCE.resolveAttributes(function.getModifierList()),
function.getName(),
typeParameterDescriptors,
@@ -29,4 +29,9 @@ public class MutableFunctionDescriptor extends MutableDeclarationDescriptor impl
public Type getUnsubstitutedReturnType() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public FunctionDescriptor getOriginal() {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.FunctionDescriptor;
import org.jetbrains.jet.lang.types.Type;
import java.util.List;
@@ -14,25 +15,36 @@ public interface OverloadDomain {
OverloadDomain EMPTY = new OverloadDomain() {
@Nullable
@Override
public Type getReturnTypeForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
return null;
}
@Nullable
@Override
public Type getReturnTypeForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
return null;
}
};
/**
* @param typeArguments
* @param valueArgumentTypes
* @param functionLiteralArgumentType
* @return A function descriptor with NO type parameters (they are already substituted), or null
*/
@Nullable
Type getReturnTypeForNamedArguments(
FunctionDescriptor getFunctionDescriptorForNamedArguments(
@NotNull List<Type> typeArguments,
@NotNull Map<String, Type> valueArgumentTypes,
@Nullable Type functionLiteralArgumentType);
/**
* @param typeArguments
* @param positionedValueArgumentTypes
* @return A function descriptor with NO type parameters (they are already substituted), or null
*/
@Nullable
Type getReturnTypeForPositionedArguments(
FunctionDescriptor getFunctionDescriptorForPositionedArguments(
@NotNull List<Type> typeArguments,
@NotNull List<Type> positionedValueArgumentTypes);
}
@@ -19,11 +19,6 @@ public class OverloadResolver {
@NotNull
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
return getOverloadDomain(TypeCheckerTrace.DUMMY, receiverType, outerScope, name);
}
@NotNull
public OverloadDomain getOverloadDomain(@NotNull TypeCheckerTrace trace, @Nullable Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
// TODO : extension lookup
JetScope scope = receiverType == null ? outerScope : receiverType.getMemberScope();
@@ -35,7 +30,7 @@ public class OverloadResolver {
return new OverloadDomain() {
@Override
public Type getReturnTypeForPositionedArguments(@NotNull final List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull final List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
Collection<FunctionDescriptor> possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
if (possiblyApplicableFunctions.isEmpty()) {
return null;
@@ -86,14 +81,14 @@ public class OverloadResolver {
if (applicable.size() == 0) {
return null;
} else if (applicable.size() == 1) {
return applicable.get(0).getUnsubstitutedReturnType();
return applicable.get(0);
} else {
throw new UnsupportedOperationException();
}
}
@Override
public Type getReturnTypeForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
throw new UnsupportedOperationException(); // TODO
}
};
@@ -1,13 +1,14 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author abreslav
*/
public interface FunctionDescriptor extends Annotated, Named {
public interface FunctionDescriptor extends DeclarationDescriptor {
@NotNull
List<TypeParameterDescriptor> getTypeParameters();
@@ -16,4 +17,13 @@ public interface FunctionDescriptor extends Annotated, Named {
@NotNull
Type getUnsubstitutedReturnType();
/**
* @return The descriptor that corresponds to the original declaration of this function.
* A descriptor can be obtained from its original by substituting type arguments (of the declaring class
* or of the function itself).
* null if the current descriptor is original itself
*/
@Nullable
FunctionDescriptor getOriginal();
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetFunction;
import java.util.*;
@@ -15,15 +16,19 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl<JetFunctio
private final List<ValueParameterDescriptor> unsubstitutedValueParameters;
@NotNull
private final Type unsubstitutedReturnType;
@Nullable
private final FunctionDescriptor original;
public FunctionDescriptorImpl(
JetFunction psiElement,
@Nullable FunctionDescriptor original,
@NotNull List<Attribute> attributes,
String name,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@NotNull Type unsubstitutedReturnType) {
super(psiElement, attributes, name);
this.original = original;
this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType;
@@ -47,4 +52,9 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl<JetFunctio
return unsubstitutedReturnType;
}
@Override
public FunctionDescriptor getOriginal() {
return original;
}
}
@@ -79,6 +79,7 @@ public class FunctionDescriptorUtil {
public static FunctionDescriptor substituteFunctionDescriptor(@NotNull List<Type> typeArguments, @NotNull FunctionDescriptor functionDescriptor) {
return new FunctionDescriptorImpl(
ResolveUtil.getJetFunction(functionDescriptor),
functionDescriptor,
// TODO : substitute
functionDescriptor.getAttributes(),
functionDescriptor.getName(),
@@ -299,7 +299,7 @@ public class JetTypeChecker {
// TODO : check that all are named
throw new UnsupportedOperationException(); // TODO
// result[0] = overloadDomain.getReturnTypeForNamedArguments(typeArguments, valueArguments, functionLiteralArgument);
// result[0] = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArguments, functionLiteralArgument);
} else {
List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
for (JetArgument argument : valueArguments) {
@@ -319,7 +319,10 @@ public class JetTypeChecker {
valueArgumentTypes.add(getType(scope, valueArgument, false));
}
result[0] = overloadDomain.getReturnTypeForPositionedArguments(types, valueArgumentTypes);
FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
if (functionDescriptor != null) {
result[0] = functionDescriptor.getUnsubstitutedReturnType();
}
}
}
@@ -334,6 +337,7 @@ public class JetTypeChecker {
private OverloadDomain getOverloadDomain(final JetScope scope, JetExpression calleeExpression) {
final OverloadDomain[] result = new OverloadDomain[1];
final JetReferenceExpression[] reference = new JetReferenceExpression[1];
calleeExpression.accept(new JetVisitor() {
@Override
@@ -357,6 +361,7 @@ public class JetTypeChecker {
Type receiverType = getType(scope, expression.getReceiverExpression(), false);
result[0] = OverloadResolver.INSTANCE.getOverloadDomain(receiverType, scope, referenceExpression.getReferencedName());
reference[0] = referenceExpression;
} else {
throw new UnsupportedOperationException(); // TODO
}
@@ -366,6 +371,7 @@ public class JetTypeChecker {
public void visitReferenceExpression(JetReferenceExpression expression) {
// a -- create a hierarchical lookup domain for this.a
result[0] = OverloadResolver.INSTANCE.getOverloadDomain(null, scope, expression.getReferencedName());
reference[0] = expression;
}
@Override
@@ -379,7 +385,21 @@ public class JetTypeChecker {
throw new IllegalArgumentException("Unsupported element: " + elem);
}
});
return result[0];
return new OverloadDomain() {
@Override
public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
FunctionDescriptor descriptor = result[0].getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType);
trace.recordResolutionResult(reference[0], descriptor);
return descriptor;
}
@Override
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
FunctionDescriptor descriptor = result[0].getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes);
trace.recordResolutionResult(reference[0], descriptor);
return descriptor;
}
};
}
private Type getBlockReturnedType(@NotNull JetScope outerScope, List<JetElement> block) {
@@ -58,6 +58,11 @@ public class LazySubstitutingFunctionDescriptor implements FunctionDescriptor {
return TypeSubstitutor.INSTANCE.substitute(substitutionContext, functionDescriptor.getUnsubstitutedReturnType(), Variance.OUT_VARIANCE);
}
@Override
public FunctionDescriptor getOriginal() {
return functionDescriptor;
}
@Override
public List<Attribute> getAttributes() {
// TODO : Substitute?
+1
View File
@@ -4,6 +4,7 @@ class A {
}
fun foo(a : Int) = a
fun fooB() = foo(1)
fun foo() : Int = 1
fun foo1() : B = new B()
}
@@ -40,16 +40,12 @@ public class JetResolveTest extends LightDaemonAnalyzerTestCase {
ClassDescriptor classB = membersOfA.getClass("B");
assertNotNull(classB);
FunctionGroup foo = membersOfA.getFunctionGroup("foo");
assertFalse(foo.isEmpty());
FunctionGroup fooFG = membersOfA.getFunctionGroup("foo");
assertFalse(fooFG.isEmpty());
OverloadDomain overloadsForFoo = OverloadResolver.INSTANCE.getOverloadDomain(null, membersOfA, "foo");
Type fooType = overloadsForFoo.getReturnTypeForPositionedArguments(Collections.<Type>emptyList(), Collections.<Type>emptyList());
assertEquals(JetStandardClasses.getIntType(), fooType);
OverloadDomain overloadsForFoo1 = OverloadResolver.INSTANCE.getOverloadDomain(null, membersOfA, "foo1");
Type foo1Type = overloadsForFoo1.getReturnTypeForPositionedArguments(Collections.<Type>emptyList(), Collections.<Type>emptyList());
assertEquals(new TypeImpl(classB), foo1Type);
assertReturnType(membersOfA, "foo", JetStandardClasses.getIntType());
assertReturnType(membersOfA, "foo1", new TypeImpl(classB));
assertReturnType(membersOfA, "fooB", JetStandardClasses.getIntType());
JetFunction fooDecl = (JetFunction) classADecl.getDeclarations().get(1);
Type expressionType = bindingContext.getExpressionType(fooDecl.getBodyExpression());
@@ -58,6 +54,12 @@ public class JetResolveTest extends LightDaemonAnalyzerTestCase {
DeclarationDescriptor resolve = bindingContext.resolve((JetReferenceExpression) fooDecl.getBodyExpression());
assertSame(bindingContext.getFunctionDescriptor(fooDecl).getUnsubstitutedValueParameters().get(0), resolve);
JetFunction fooBDecl = (JetFunction) classADecl.getDeclarations().get(2);
JetCallExpression fooBBody = (JetCallExpression) fooBDecl.getBodyExpression();
JetReferenceExpression refToFoo = (JetReferenceExpression) fooBBody.getCalleeExpression();
FunctionDescriptor mustBeFoo = (FunctionDescriptor) bindingContext.resolve(refToFoo);
assertSame(bindingContext.getFunctionDescriptor(fooDecl), mustBeFoo.getOriginal());
JetClass classCDecl = (JetClass) declarations.get(1);
ClassDescriptor classC = bindingContext.getClassDescriptor(classCDecl);
assertNotNull(classC);
@@ -69,7 +71,13 @@ public class JetResolveTest extends LightDaemonAnalyzerTestCase {
assertNotNull(classC_B);
assertNotSame(classC_B, classB);
assertEquals(classC.getTypeConstructor(), classC_B.getTypeConstructor().getSupertypes().iterator().next().getConstructor());
}
private void assertReturnType(JetScope membersOfA, String foo, Type returnType) {
OverloadDomain overloadsForFoo = OverloadResolver.INSTANCE.getOverloadDomain(null, membersOfA, foo);
FunctionDescriptor descriptorForFoo = overloadsForFoo.getFunctionDescriptorForPositionedArguments(Collections.<Type>emptyList(), Collections.<Type>emptyList());
assertNotNull(descriptorForFoo);
Type fooType = descriptorForFoo.getUnsubstitutedReturnType();
assertEquals(returnType, fooType);
}
}