diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 5cf4b728080..ee6f16389f3 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -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, diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java index 71b8a6d9003..bf1b26d096e 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java @@ -29,5 +29,5 @@ public interface JetScope { Type getThisType(); @NotNull - OverloadDomain getOverloadDomain(@Nullable Type receiverType, @NotNull String referencedName); + FunctionGroup getFunctionGroup(@NotNull String name); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java index a9144680a59..8a6d56c9117 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java @@ -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); - } -} +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java index 3746ad1e585..5ee66446eec 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java @@ -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; } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java new file mode 100644 index 00000000000..01b470a3972 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java @@ -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 typeArguments, @NotNull List positionedValueArgumentTypes) { + Collection possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes); + if (possiblyApplicableFunctions.isEmpty()) { + return null; + } + + List applicable = new ArrayList(); + + descLoop: + for (FunctionDescriptor descriptor : possiblyApplicableFunctions) { + // ASSERT: type arguments are figured out and substituted by this time!!! + assert descriptor.getTypeParameters().isEmpty(); + + List 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 typeArguments, @NotNull Map valueArgumentTypes, @Nullable Type functionLiteralArgumentType) { + throw new UnsupportedOperationException(); // TODO + } + }; + } + +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java index e3f848a945d..773d56ca1ca 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java @@ -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)); } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java b/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java index 85ef019a4ed..1657909d03e 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java @@ -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 typeArguments, FunctionDescriptor functionDescriptor) { - return new FunctionDescriptor( - // TODO : substitute - functionDescriptor.getAttributes(), - functionDescriptor.getName(), - Collections.emptyList(), // TODO : questionable - functionDescriptor.getSubstitutedValueParameters(typeArguments), - functionDescriptor.getSubstitutedReturnType(typeArguments) - ); + @Override + public boolean isEmpty() { + return functionDescriptors.isEmpty(); } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java b/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java index c35d480cc92..ebfbf1cbd04 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java @@ -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 typeArguments, @NotNull List positionedValueArgumentTypes) { - Collection possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes); - if (possiblyApplicableFunctions.isEmpty()) { - return null; - } - - List applicable = new ArrayList(); - - descLoop: - for (FunctionDescriptor descriptor : possiblyApplicableFunctions) { - // ASSERT: type arguments are figured out and substituted by this time!!! - assert descriptor.getTypeParameters().isEmpty(); - - List 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 typeArguments, @NotNull Map valueArgumentTypes, @Nullable Type functionLiteralArgumentType) { - throw new UnsupportedOperationException(); // TODO - } - }; - } - @Override public ClassDescriptor getClass(String name) { throw new UnsupportedOperationException(); // TODO diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java index b28ab789396..21b9c0b01e9 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java @@ -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() {} diff --git a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java index 72fd3828596..6ecc529aef7 100644 --- a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java @@ -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 typeParameters; - @NotNull - private final List unsubstitutedValueParameters; - @NotNull - private final Type unsubstitutedReturnType; - - public FunctionDescriptor( - @NotNull List attributes, - String name, - @NotNull List typeParameters, - @NotNull List unsubstitutedValueParameters, - @NotNull Type unsubstitutedReturnType) { - super(attributes, name); - this.typeParameters = typeParameters; - this.unsubstitutedValueParameters = unsubstitutedValueParameters; - this.unsubstitutedReturnType = unsubstitutedReturnType; - } + List getTypeParameters(); @NotNull - public List getTypeParameters() { - return typeParameters; - } + List getUnsubstitutedValueParameters(); @NotNull - public List 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 getSubstitutedValueParameters(@NotNull List typeArguments) { - List result = new ArrayList(); - Map 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 createSubstitutionContext(List typeArguments) { - Map result = new HashMap(); - - 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 typeArguments) { - return TypeSubstitutor.INSTANCE.substitute(createSubstitutionContext(typeArguments), unsubstitutedReturnType, Variance.OUT_VARIANCE); - } + Type getUnsubstitutedReturnType(); } diff --git a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java new file mode 100644 index 00000000000..e9f6a2df63e --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java @@ -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 typeParameters; + @NotNull + private final List unsubstitutedValueParameters; + @NotNull + private final Type unsubstitutedReturnType; + + public FunctionDescriptorImpl( + @NotNull List attributes, + String name, + @NotNull List typeParameters, + @NotNull List unsubstitutedValueParameters, + @NotNull Type unsubstitutedReturnType) { + super(attributes, name); + this.typeParameters = typeParameters; + this.unsubstitutedValueParameters = unsubstitutedValueParameters; + this.unsubstitutedReturnType = unsubstitutedReturnType; + } + + @Override + @NotNull + public List getTypeParameters() { + return typeParameters; + } + + @Override + @NotNull + public List getUnsubstitutedValueParameters() { + return unsubstitutedValueParameters; + } + + @Override + @NotNull + public Type getUnsubstitutedReturnType() { + return unsubstitutedReturnType; + } + +} diff --git a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorUtil.java b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorUtil.java new file mode 100644 index 00000000000..2a1c2f7d91f --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorUtil.java @@ -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 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 getSubstitutedValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull List typeArguments) { + List result = new ArrayList(); + Map 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 createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List typeArguments) { + Map result = new HashMap(); + + int typeArgumentsSize = typeArguments.size(); + List 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 typeArguments) { + return TypeSubstitutor.INSTANCE.substitute(createSubstitutionContext(functionDescriptor, typeArguments), functionDescriptor.getUnsubstitutedReturnType(), Variance.OUT_VARIANCE); + } + + @NotNull + public static FunctionDescriptor substituteFunctionDescriptor(@NotNull List typeArguments, @NotNull FunctionDescriptor functionDescriptor) { + return new FunctionDescriptorImpl( + // TODO : substitute + functionDescriptor.getAttributes(), + functionDescriptor.getName(), + Collections.emptyList(), // TODO : questionable + getSubstitutedValueParameters(functionDescriptor, typeArguments), + getSubstitutedReturnType(functionDescriptor, typeArguments) + ); + } + +} diff --git a/idea/src/org/jetbrains/jet/lang/types/FunctionGroup.java b/idea/src/org/jetbrains/jet/lang/types/FunctionGroup.java index 19fac0d1b31..edb131d8364 100644 --- a/idea/src/org/jetbrains/jet/lang/types/FunctionGroup.java +++ b/idea/src/org/jetbrains/jet/lang/types/FunctionGroup.java @@ -21,6 +21,11 @@ public interface FunctionGroup extends Named { public Collection getPossiblyApplicableFunctions(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes) { return Collections.emptySet(); } + + @Override + public boolean isEmpty() { + return true; + } }; @@ -30,4 +35,6 @@ public interface FunctionGroup extends Named { @NotNull Collection getPossiblyApplicableFunctions(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes); + + boolean isEmpty(); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index a8469a30597..b682598c5dd 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -293,7 +293,8 @@ public class JetTypeChecker { } List 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 types = new ArrayList(); @@ -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 } diff --git a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java new file mode 100644 index 00000000000..e558d50218b --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java @@ -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 substitutionContext; + private final FunctionDescriptor functionDescriptor; + + public LazySubstitutingFunctionDescriptor(Map substitutionContext, FunctionDescriptor functionDescriptor) { + this.substitutionContext = substitutionContext; + this.functionDescriptor = functionDescriptor; + } + + @NotNull + @Override + public List getTypeParameters() { + List result = new ArrayList(); + 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 getUnsubstitutedValueParameters() { + List result = new ArrayList(); + 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 getAttributes() { + // TODO : Substitute? + return functionDescriptor.getAttributes(); + } + + @Override + public String getName() { + return functionDescriptor.getName(); + } +} + diff --git a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionGroup.java b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionGroup.java new file mode 100644 index 00000000000..8cd475c6f86 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionGroup.java @@ -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 substitutionContext; + private final FunctionGroup functionGroup; + + public LazySubstitutingFunctionGroup(Map substitutionContext, FunctionGroup functionGroup) { + this.substitutionContext = substitutionContext; + this.functionGroup = functionGroup; + } + + @NotNull + @Override + public String getName() { + return functionGroup.getName(); + } + + @NotNull + @Override + public Collection getPossiblyApplicableFunctions(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes) { + Collection possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes); + Collection result = new ArrayList(); + for (FunctionDescriptor function : possiblyApplicableFunctions) { + result.add(new LazySubstitutingFunctionDescriptor(substitutionContext, function)); + } + return result; + } + + @Override + public boolean isEmpty() { + return functionGroup.isEmpty(); + } +} diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java index d6bacbd1e2d..2bc50770c39 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -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 newArguments) { return new TypeImpl(type.getAttributes(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope()); } + + public Set substituteInSet(Map substitutionContext, Set types, Variance howTheseTypesWillBeUsed) { + Set result = new HashSet(); + for (Type type : types) { + result.add(substitute(substitutionContext, type, howTheseTypesWillBeUsed)); + } + return result; + } }