Substitutions work in basic cases

This commit is contained in:
Andrey Breslav
2011-02-21 18:13:33 +03:00
parent 0dd7118678
commit c2c3d92abc
17 changed files with 393 additions and 208 deletions
@@ -102,7 +102,7 @@ public class ClassDescriptorResolver {
returnType = JetTypeChecker.INSTANCE.getType(parameterScope, bodyExpression, function.hasBlockBody());
}
return new FunctionDescriptor(
return new FunctionDescriptorImpl(
AttributeResolver.INSTANCE.resolveAttributes(function.getModifierList()),
function.getName(),
typeParameterDescriptors,
@@ -29,5 +29,5 @@ public interface JetScope {
Type getThisType();
@NotNull
OverloadDomain getOverloadDomain(@Nullable Type receiverType, @NotNull String referencedName);
FunctionGroup getFunctionGroup(@NotNull String name);
}
@@ -19,6 +19,12 @@ public class JetScopeAdapter implements JetScope {
return scope.getThisType();
}
@NotNull
@Override
public FunctionGroup getFunctionGroup(@NotNull String name) {
return scope.getFunctionGroup(name);
}
@Override
public TypeParameterDescriptor getTypeParameter(String name) {
return scope.getTypeParameter(name);
@@ -44,9 +50,4 @@ public class JetScopeAdapter implements JetScope {
return scope.getExtension(name);
}
@NotNull
@Override
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
return scope.getOverloadDomain(receiverType, referencedName);
}
}
}
@@ -40,7 +40,7 @@ public abstract class JetScopeImpl implements JetScope {
@NotNull
@Override
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
return receiverType.getMemberScope().getOverloadDomain(null, referencedName);
public FunctionGroup getFunctionGroup(@NotNull String name) {
return FunctionGroup.EMPTY;
}
}
@@ -0,0 +1,97 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class OverloadResolver {
public static final OverloadResolver INSTANCE = new OverloadResolver();
private OverloadResolver() {}
@NotNull
public OverloadDomain getOverloadDomain(@Nullable Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
// TODO : extension lookup
JetScope scope = receiverType == null ? outerScope : receiverType.getMemberScope();
final FunctionGroup functionGroup = scope.getFunctionGroup(name);
if (functionGroup.isEmpty()) {
return OverloadDomain.EMPTY;
}
return new OverloadDomain() {
@Override
public Type getReturnTypeForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
Collection<FunctionDescriptor> possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
if (possiblyApplicableFunctions.isEmpty()) {
return null;
}
List<FunctionDescriptor> applicable = new ArrayList<FunctionDescriptor>();
descLoop:
for (FunctionDescriptor descriptor : possiblyApplicableFunctions) {
// ASSERT: type arguments are figured out and substituted by this time!!!
assert descriptor.getTypeParameters().isEmpty();
List<ValueParameterDescriptor> parameters = descriptor.getUnsubstitutedValueParameters();
if (parameters.size() >= positionedValueArgumentTypes.size()) {
// possibly, some default values
// possibly, nothing passed to a vararg
// possibly, a single value passed to a vararg
// possibly an array/list/etc passed as a whole vararg
for (int i = 0, positionedValueArgumentTypesSize = positionedValueArgumentTypes.size(); i < positionedValueArgumentTypesSize; i++) {
Type argumentType = positionedValueArgumentTypes.get(i);
Type parameterType = parameters.get(i).getType();
// TODO : handle vararg cases here
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) {
continue descLoop;
}
}
} else {
// vararg
int nonVarargs = parameters.size() - 1;
for (int i = 0; i < nonVarargs; i++) {
Type argumentType = positionedValueArgumentTypes.get(i);
Type parameterType = parameters.get(i).getType();
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) {
continue descLoop;
}
}
Type varArgType = parameters.get(nonVarargs).getType();
for (int i = nonVarargs, args = positionedValueArgumentTypes.size(); i < args; i++) {
Type argumentType = positionedValueArgumentTypes.get(i);
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, varArgType)) {
continue descLoop;
}
}
}
applicable.add(descriptor);
}
if (applicable.size() == 0) {
return null;
} else if (applicable.size() == 1) {
return applicable.get(0).getUnsubstitutedReturnType();
} else {
throw new UnsupportedOperationException();
}
}
@Override
public Type getReturnTypeForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
throw new UnsupportedOperationException(); // TODO
}
};
}
}
@@ -55,9 +55,7 @@ public class SubstitutingScope implements JetScope {
@NotNull
@Override
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
final OverloadDomain workerDomain = workerScope.getOverloadDomain(receiverType, referencedName);
// TODO: !!!
return workerDomain;
public FunctionGroup getFunctionGroup(@NotNull String name) {
return new LazySubstitutingFunctionGroup(substitutionContext, workerScope.getFunctionGroup(name));
}
}
@@ -1,14 +1,10 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.FunctionDescriptor;
import org.jetbrains.jet.lang.types.FunctionGroup;
import org.jetbrains.jet.lang.types.Type;
import org.jetbrains.jet.lang.types.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -55,22 +51,16 @@ public class WritableFunctionGroup implements FunctionGroup {
for (FunctionDescriptor functionDescriptor : getFunctionDescriptors()) {
// TODO : type argument inference breaks this logic
if (functionDescriptor.getTypeParameters().size() == typeArgCount) {
if (functionDescriptor.getMinimumArity() <= valueArgCount && valueArgCount <= functionDescriptor.getMaximumArity()) {
result.add(substituteFunctionDescriptor(typeArguments, functionDescriptor));
if (FunctionDescriptorUtil.getMinimumArity(functionDescriptor) <= valueArgCount && valueArgCount <= FunctionDescriptorUtil.getMaximumArity(functionDescriptor)) {
result.add(FunctionDescriptorUtil.substituteFunctionDescriptor(typeArguments, functionDescriptor));
}
}
}
return result;
}
private FunctionDescriptor substituteFunctionDescriptor(List<Type> typeArguments, FunctionDescriptor functionDescriptor) {
return new FunctionDescriptor(
// TODO : substitute
functionDescriptor.getAttributes(),
functionDescriptor.getName(),
Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable
functionDescriptor.getSubstitutedValueParameters(typeArguments),
functionDescriptor.getSubstitutedReturnType(typeArguments)
);
@Override
public boolean isEmpty() {
return functionDescriptors.isEmpty();
}
}
@@ -57,8 +57,9 @@ public class WritableScope implements JetScope {
functionGroup.addFunction(functionDescriptor);
}
@Override
@NotNull
private FunctionGroup getFunctionGroup(String name) {
public FunctionGroup getFunctionGroup(@NotNull String name) {
WritableFunctionGroup functionGroup = getFunctionGroups().get(name);
if (functionGroup == null) {
return FunctionGroup.EMPTY;
@@ -66,80 +67,6 @@ public class WritableScope implements JetScope {
return functionGroup;
}
@NotNull
@Override
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
final FunctionGroup functionGroup = getFunctionGroups().get(referencedName);
if (functionGroup == null) {
return OverloadDomain.EMPTY;
}
return new OverloadDomain() {
@Override
public Type getReturnTypeForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
Collection<FunctionDescriptor> possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
if (possiblyApplicableFunctions.isEmpty()) {
return null;
}
List<FunctionDescriptor> applicable = new ArrayList<FunctionDescriptor>();
descLoop:
for (FunctionDescriptor descriptor : possiblyApplicableFunctions) {
// ASSERT: type arguments are figured out and substituted by this time!!!
assert descriptor.getTypeParameters().isEmpty();
List<ValueParameterDescriptor> parameters = descriptor.getUnsubstitutedValueParameters();
if (parameters.size() >= positionedValueArgumentTypes.size()) {
// possibly, some default values
// possibly, nothing passed to a vararg
// possibly, a single value passed to a vararg
// possibly an array/list/etc passed as a whole vararg
for (int i = 0, positionedValueArgumentTypesSize = positionedValueArgumentTypes.size(); i < positionedValueArgumentTypesSize; i++) {
Type argumentType = positionedValueArgumentTypes.get(i);
Type parameterType = parameters.get(i).getType();
// TODO : handle vararg cases here
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) {
continue descLoop;
}
}
} else {
// vararg
int nonVarargs = parameters.size() - 1;
for (int i = 0; i < nonVarargs; i++) {
Type argumentType = positionedValueArgumentTypes.get(i);
Type parameterType = parameters.get(i).getType();
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) {
continue descLoop;
}
}
Type varArgType = parameters.get(nonVarargs).getType();
for (int i = nonVarargs, args = positionedValueArgumentTypes.size(); i < args; i++) {
Type argumentType = positionedValueArgumentTypes.get(i);
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, varArgType)) {
continue descLoop;
}
}
}
applicable.add(descriptor);
}
if (applicable.size() == 0) {
return null;
} else if (applicable.size() == 1) {
return applicable.get(0).getUnsubstitutedReturnType();
} else {
throw new UnsupportedOperationException();
}
}
@Override
public Type getReturnTypeForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
throw new UnsupportedOperationException(); // TODO
}
};
}
@Override
public ClassDescriptor getClass(String name) {
throw new UnsupportedOperationException(); // TODO
@@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.OverloadDomain;
import java.util.Collections;
import java.util.List;
@@ -45,9 +44,10 @@ public class ErrorType {
@NotNull
@Override
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
public FunctionGroup getFunctionGroup(@NotNull String name) {
throw new UnsupportedOperationException(); // TODO
}
};
private ErrorType() {}
@@ -2,109 +2,18 @@ package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class FunctionDescriptor extends MemberDescriptorImpl {
public interface FunctionDescriptor extends Annotated, Named {
@NotNull
private final List<TypeParameterDescriptor> typeParameters;
@NotNull
private final List<ValueParameterDescriptor> unsubstitutedValueParameters;
@NotNull
private final Type unsubstitutedReturnType;
public FunctionDescriptor(
@NotNull List<Attribute> attributes,
String name,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@NotNull Type unsubstitutedReturnType) {
super(attributes, name);
this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType;
}
List<TypeParameterDescriptor> getTypeParameters();
@NotNull
public List<TypeParameterDescriptor> getTypeParameters() {
return typeParameters;
}
List<ValueParameterDescriptor> getUnsubstitutedValueParameters();
@NotNull
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
return unsubstitutedValueParameters;
}
@NotNull
public Type getUnsubstitutedReturnType() {
return unsubstitutedReturnType;
}
/** @return Minimal number of arguments to be passed */
public int getMinimumArity() {
int result = 0;
for (ValueParameterDescriptor valueParameter : unsubstitutedValueParameters) {
if (valueParameter.hasDefaultValue()) {
break;
}
result++;
}
return result;
}
/**
* @return Maximum number of arguments that can be passed. -1 if unbound (vararg)
*/
public int getMaximumArity() {
if (unsubstitutedValueParameters.isEmpty()) {
return 0;
}
// TODO : check somewhere that vararg is only the last one, and that varargs do not have default values
ValueParameterDescriptor lastParameter = unsubstitutedValueParameters.get(unsubstitutedValueParameters.size() - 1);
if (lastParameter.isVararg()) {
return -1;
}
return unsubstitutedValueParameters.size();
}
@NotNull
public List<ValueParameterDescriptor> getSubstitutedValueParameters(@NotNull List<Type> typeArguments) {
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
Map<TypeConstructor,TypeProjection> context = createSubstitutionContext(typeArguments);
for (ValueParameterDescriptor unsubstitutedValueParameter : unsubstitutedValueParameters) {
// TODO : Lazy?
result.add(new ValueParameterDescriptorImpl(
unsubstitutedValueParameter.getAttributes(),
unsubstitutedValueParameter.getName(),
TypeSubstitutor.INSTANCE.substitute(context, unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE),
unsubstitutedValueParameter.hasDefaultValue(),
unsubstitutedValueParameter.isVararg()
));
}
return result;
}
private Map<TypeConstructor, TypeProjection> createSubstitutionContext(List<Type> typeArguments) {
Map<TypeConstructor,TypeProjection> result = new HashMap<TypeConstructor, TypeProjection>();
int typeArgumentsSize = typeArguments.size();
assert typeArgumentsSize == typeParameters.size();
for (int i = 0; i < typeArgumentsSize; i++) {
TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
Type typeArgument = typeArguments.get(i);
result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(typeArgument));
}
return result;
}
@NotNull
public Type getSubstitutedReturnType(@NotNull List<Type> typeArguments) {
return TypeSubstitutor.INSTANCE.substitute(createSubstitutionContext(typeArguments), unsubstitutedReturnType, Variance.OUT_VARIANCE);
}
Type getUnsubstitutedReturnType();
}
@@ -0,0 +1,48 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* @author abreslav
*/
public class FunctionDescriptorImpl extends MemberDescriptorImpl implements FunctionDescriptor {
@NotNull
private final List<TypeParameterDescriptor> typeParameters;
@NotNull
private final List<ValueParameterDescriptor> unsubstitutedValueParameters;
@NotNull
private final Type unsubstitutedReturnType;
public FunctionDescriptorImpl(
@NotNull List<Attribute> attributes,
String name,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@NotNull Type unsubstitutedReturnType) {
super(attributes, name);
this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType;
}
@Override
@NotNull
public List<TypeParameterDescriptor> getTypeParameters() {
return typeParameters;
}
@Override
@NotNull
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
return unsubstitutedValueParameters;
}
@Override
@NotNull
public Type getUnsubstitutedReturnType() {
return unsubstitutedReturnType;
}
}
@@ -0,0 +1,88 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* @author abreslav
*/
public class FunctionDescriptorUtil {
/** @return Minimal number of arguments to be passed */
public static int getMinimumArity(@NotNull FunctionDescriptor functionDescriptor) {
int result = 0;
for (ValueParameterDescriptor valueParameter : functionDescriptor.getUnsubstitutedValueParameters()) {
if (valueParameter.hasDefaultValue()) {
break;
}
result++;
}
return result;
}
/**
* @return Maximum number of arguments that can be passed. -1 if unbound (vararg)
*/
public static int getMaximumArity(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getUnsubstitutedValueParameters();
if (unsubstitutedValueParameters.isEmpty()) {
return 0;
}
// TODO : check somewhere that vararg is only the last one, and that varargs do not have default values
ValueParameterDescriptor lastParameter = unsubstitutedValueParameters.get(unsubstitutedValueParameters.size() - 1);
if (lastParameter.isVararg()) {
return -1;
}
return unsubstitutedValueParameters.size();
}
@NotNull
public static List<ValueParameterDescriptor> getSubstitutedValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull List<Type> typeArguments) {
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
Map<TypeConstructor, TypeProjection> context = createSubstitutionContext(functionDescriptor, typeArguments);
for (ValueParameterDescriptor unsubstitutedValueParameter : functionDescriptor.getUnsubstitutedValueParameters()) {
// TODO : Lazy?
result.add(new ValueParameterDescriptorImpl(
unsubstitutedValueParameter.getAttributes(),
unsubstitutedValueParameter.getName(),
TypeSubstitutor.INSTANCE.substitute(context, unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE),
unsubstitutedValueParameter.hasDefaultValue(),
unsubstitutedValueParameter.isVararg()
));
}
return result;
}
private static Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<Type> typeArguments) {
Map<TypeConstructor,TypeProjection> result = new HashMap<TypeConstructor, TypeProjection>();
int typeArgumentsSize = typeArguments.size();
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
assert typeArgumentsSize == typeParameters.size();
for (int i = 0; i < typeArgumentsSize; i++) {
TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
Type typeArgument = typeArguments.get(i);
result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(typeArgument));
}
return result;
}
@NotNull
public static Type getSubstitutedReturnType(@NotNull FunctionDescriptor functionDescriptor, @NotNull List<Type> typeArguments) {
return TypeSubstitutor.INSTANCE.substitute(createSubstitutionContext(functionDescriptor, typeArguments), functionDescriptor.getUnsubstitutedReturnType(), Variance.OUT_VARIANCE);
}
@NotNull
public static FunctionDescriptor substituteFunctionDescriptor(@NotNull List<Type> typeArguments, @NotNull FunctionDescriptor functionDescriptor) {
return new FunctionDescriptorImpl(
// TODO : substitute
functionDescriptor.getAttributes(),
functionDescriptor.getName(),
Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable
getSubstitutedValueParameters(functionDescriptor, typeArguments),
getSubstitutedReturnType(functionDescriptor, typeArguments)
);
}
}
@@ -21,6 +21,11 @@ public interface FunctionGroup extends Named {
public Collection<FunctionDescriptor> getPossiblyApplicableFunctions(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
return Collections.emptySet();
}
@Override
public boolean isEmpty() {
return true;
}
};
@@ -30,4 +35,6 @@ public interface FunctionGroup extends Named {
@NotNull
Collection<FunctionDescriptor> getPossiblyApplicableFunctions(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes);
boolean isEmpty();
}
@@ -293,7 +293,8 @@ public class JetTypeChecker {
}
List<JetExpression> functionLiteralArguments = expression.getFunctionLiteralArguments();
JetExpression functionLiteralArgument = functionLiteralArguments.isEmpty() ? null : functionLiteralArguments.get(0);
// JetExpression functionLiteralArgument = functionLiteralArguments.isEmpty() ? null : functionLiteralArguments.get(0);
// TODO : must be a check
assert functionLiteralArguments.size() <= 1;
OverloadDomain overloadDomain = getOverloadDomain(scope, calleeExpression);
@@ -307,6 +308,7 @@ public class JetTypeChecker {
for (JetArgument argument : valueArguments) {
positionedValueArguments.add(argument.getArgumentExpression());
}
positionedValueArguments.addAll(functionLiteralArguments);
List<Type> types = new ArrayList<Type>();
@@ -356,7 +358,7 @@ public class JetTypeChecker {
JetReferenceExpression referenceExpression = (JetReferenceExpression) selectorExpression;
Type receiverType = getType(scope, expression.getReceiverExpression(), false);
result[0] = scope.getOverloadDomain(receiverType, referenceExpression.getReferencedName());
result[0] = OverloadResolver.INSTANCE.getOverloadDomain(receiverType, scope, referenceExpression.getReferencedName());
} else {
throw new UnsupportedOperationException(); // TODO
}
@@ -0,0 +1,70 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class LazySubstitutingFunctionDescriptor implements FunctionDescriptor {
private final Map<TypeConstructor, TypeProjection> substitutionContext;
private final FunctionDescriptor functionDescriptor;
public LazySubstitutingFunctionDescriptor(Map<TypeConstructor, TypeProjection> substitutionContext, FunctionDescriptor functionDescriptor) {
this.substitutionContext = substitutionContext;
this.functionDescriptor = functionDescriptor;
}
@NotNull
@Override
public List<TypeParameterDescriptor> getTypeParameters() {
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>();
for (TypeParameterDescriptor parameterDescriptor : functionDescriptor.getTypeParameters()) {
// TODO : lazy?
result.add(new TypeParameterDescriptor(
parameterDescriptor.getAttributes(),
parameterDescriptor.getVariance(),
parameterDescriptor.getName(),
TypeSubstitutor.INSTANCE.substituteInSet(substitutionContext, parameterDescriptor.getUpperBounds(), Variance.INVARIANT)));
}
return result;
}
@NotNull
@Override
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getUnsubstitutedValueParameters()) {
result.add(new ValueParameterDescriptorImpl(
parameterDescriptor.getAttributes(),
parameterDescriptor.getName(),
TypeSubstitutor.INSTANCE.substitute(substitutionContext, parameterDescriptor.getType(), Variance.IN_VARIANCE),
parameterDescriptor.hasDefaultValue(),
parameterDescriptor.isVararg()
));
}
return result;
}
@NotNull
@Override
public Type getUnsubstitutedReturnType() {
return TypeSubstitutor.INSTANCE.substitute(substitutionContext, functionDescriptor.getUnsubstitutedReturnType(), Variance.OUT_VARIANCE);
}
@Override
public List<Attribute> getAttributes() {
// TODO : Substitute?
return functionDescriptor.getAttributes();
}
@Override
public String getName() {
return functionDescriptor.getName();
}
}
@@ -0,0 +1,43 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class LazySubstitutingFunctionGroup implements FunctionGroup {
private final Map<TypeConstructor, TypeProjection> substitutionContext;
private final FunctionGroup functionGroup;
public LazySubstitutingFunctionGroup(Map<TypeConstructor, TypeProjection> substitutionContext, FunctionGroup functionGroup) {
this.substitutionContext = substitutionContext;
this.functionGroup = functionGroup;
}
@NotNull
@Override
public String getName() {
return functionGroup.getName();
}
@NotNull
@Override
public Collection<FunctionDescriptor> getPossiblyApplicableFunctions(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
Collection<FunctionDescriptor> possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
Collection<FunctionDescriptor> result = new ArrayList<FunctionDescriptor>();
for (FunctionDescriptor function : possiblyApplicableFunctions) {
result.add(new LazySubstitutingFunctionDescriptor(substitutionContext, function));
}
return result;
}
@Override
public boolean isEmpty() {
return functionGroup.isEmpty();
}
}
@@ -2,10 +2,7 @@ package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author abreslav
@@ -73,4 +70,12 @@ public class TypeSubstitutor {
private Type specializeType(Type type, List<TypeProjection> newArguments) {
return new TypeImpl(type.getAttributes(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope());
}
public Set<Type> substituteInSet(Map<TypeConstructor, TypeProjection> substitutionContext, Set<Type> types, Variance howTheseTypesWillBeUsed) {
Set<Type> result = new HashSet<Type>();
for (Type type : types) {
result.add(substitute(substitutionContext, type, howTheseTypesWillBeUsed));
}
return result;
}
}