Preliminary support for extension functions: they participate in overload resolution only if no such name is found in the receiver type itself.

This commit is contained in:
Andrey Breslav
2011-05-19 00:06:01 +04:00
parent 25799cf2f0
commit 00e2c9dde3
15 changed files with 192 additions and 20 deletions
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
@@ -26,12 +27,13 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
@Override
@Deprecated
public FunctionDescriptor initialize(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull JetType unsubstitutedReturnType) {
return super.initialize(typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType);
public FunctionDescriptor initialize(@Nullable JetType receiverType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull JetType unsubstitutedReturnType) {
assert receiverType == null;
return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType);
}
public ConstructorDescriptor initialize(@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters) {
super.initialize(Collections.<TypeParameterDescriptor>emptyList(), unsubstitutedValueParameters, getContainingDeclaration().getDefaultType());
super.initialize(null, Collections.<TypeParameterDescriptor>emptyList(), unsubstitutedValueParameters, getContainingDeclaration().getDefaultType());
return this;
}
@@ -16,8 +16,8 @@ public interface FunctionDescriptor extends DeclarationDescriptor {
@NotNull
DeclarationDescriptor getContainingDeclaration();
// @Nullable
// JetType getReceiverType();
@Nullable
JetType getReceiverType();
@NotNull
List<TypeParameterDescriptor> getTypeParameters();
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.Variance;
import java.util.Collections;
import java.util.List;
@@ -18,9 +19,9 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
private List<TypeParameterDescriptor> typeParameters;
private List<ValueParameterDescriptor> unsubstitutedValueParameters;
private JetType unsubstitutedReturnType;
private JetType receiverType;
private final Set<FunctionDescriptor> overriddenFunctions = Sets.newHashSet();
private final FunctionDescriptor original;
public FunctionDescriptorImpl(
@@ -40,15 +41,22 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
}
public FunctionDescriptor initialize(
@Nullable JetType receiverType,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType) {
this.receiverType = receiverType;
this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType;
return this;
}
@Override
public JetType getReceiverType() {
return receiverType;
}
@NotNull
@Override
public Set<? extends FunctionDescriptor> getOverriddenFunctions() {
@@ -91,6 +99,15 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
FunctionDescriptorImpl substitutedDescriptor;
substitutedDescriptor = createSubstitutedCopy();
JetType receiverType = getReceiverType();
JetType substitutedReceiverType = null;
if (receiverType != null) {
substitutedReceiverType = substitutor.substitute(receiverType, Variance.IN_VARIANCE);
if (substitutedReceiverType == null) {
return null;
}
}
List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorUtil.getSubstitutedValueParameters(substitutedDescriptor, this, substitutor);
if (substitutedValueParameters == null) {
return null;
@@ -102,6 +119,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
}
substitutedDescriptor.initialize(
substitutedReceiverType,
Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable
substitutedValueParameters,
substitutedReturnType
@@ -1,14 +1,13 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.base.Function;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.WritableScope;
import org.jetbrains.jet.lang.resolve.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.types.*;
import java.util.*;
@@ -99,6 +98,10 @@ public class FunctionDescriptorUtil {
@NotNull
public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, trace.getErrorHandler());
JetType receiverType = descriptor.getReceiverType();
if (receiverType != null) {
parameterScope.setThisType(receiverType);
}
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
parameterScope.addTypeParameterDescriptor(typeParameter);
}
@@ -229,4 +232,54 @@ public class FunctionDescriptorUtil {
return OverrideCompatibilityInfo.success();
}
@NotNull
public static FunctionGroup filteredFunctionGroup(@NotNull final FunctionGroup functionGroup, @NotNull final Function<FunctionDescriptor, Boolean> criterion) {
return new FunctionGroup() {
@NotNull
@Override
public String getName() {
return functionGroup.getName();
}
@NotNull
@Override
public OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
OverloadResolutionResult possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
List<FunctionDescriptor> functionDescriptors = Lists.newArrayList(possiblyApplicableFunctions.getFunctionDescriptors());
for (Iterator<FunctionDescriptor> iterator = functionDescriptors.iterator(); iterator.hasNext(); ) {
FunctionDescriptor functionDescriptor = iterator.next();
if (!criterion.apply(functionDescriptor)) {
iterator.remove();
}
}
if (functionDescriptors.isEmpty()) {
return OverloadResolutionResult.nameNotFound();
}
if (possiblyApplicableFunctions.isSuccess() || possiblyApplicableFunctions.isAmbiguity()) {
if (functionDescriptors.size() == 1) {
return OverloadResolutionResult.success(functionDescriptors.get(0));
}
return OverloadResolutionResult.ambiguity(functionDescriptors);
}
if (functionDescriptors.size() == 1) {
return OverloadResolutionResult.singleFunctionArgumentMismatch(functionDescriptors.get(0));
}
return OverloadResolutionResult.ambiguity(functionDescriptors);
}
@Override
public boolean isEmpty() {
// TODO: not implemented
return false;
}
@NotNull
@Override
public Set<FunctionDescriptor> getFunctionDescriptors() {
// TODO: not implemented
return null;
}
};
}
}
@@ -31,6 +31,11 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
overriddenGetters.add(overriddenGetter);
}
@Override
public JetType getReceiverType() {
return null; // TODO
}
@NotNull
@Override
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
@@ -40,6 +40,11 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
overriddenSetters.add(overriddenSetter);
}
@Override
public JetType getReceiverType() {
return null; // TODO
}
@NotNull
@Override
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
@@ -24,6 +24,18 @@ public class JetFunction extends JetTypeParameterListOwner implements JetDeclara
visitor.visitFunction(this);
}
public boolean hasTypeParameterListBeforeFunctionName() {
JetTypeParameterList typeParameterList = getTypeParameterList();
if (typeParameterList == null) {
return false;
}
PsiElement nameIdentifier = getNameIdentifier();
if (nameIdentifier == null) {
return false;
}
return nameIdentifier.getTextOffset() > typeParameterList.getTextOffset();
}
@Nullable @IfNotParsed
public JetParameterList getValueParameterList() {
return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST);
@@ -174,8 +174,19 @@ public class ClassDescriptorResolver {
WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler());
innerScope.addLabeledDeclaration(functionDescriptor);
// The two calls below have side-effects on parameterScope
List<TypeParameterDescriptor> typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters());
JetType receiverType = null;
JetTypeReference receiverTypeRef = function.getReceiverTypeRef();
if (receiverTypeRef != null) {
JetScope scopeForReceiver =
function.hasTypeParameterListBeforeFunctionName()
? innerScope
: scope;
receiverType = typeResolver.resolveType(scopeForReceiver, receiverTypeRef);
}
List<ValueParameterDescriptor> valueParameterDescriptors = resolveValueParameters(functionDescriptor, innerScope, function.getValueParameters());
JetTypeReference returnTypeRef = function.getReturnTypeRef();
@@ -201,6 +212,7 @@ public class ClassDescriptorResolver {
}
functionDescriptor.initialize(
receiverType,
typeParameterDescriptors,
valueParameterDescriptors,
returnType);
@@ -23,7 +23,7 @@ public class OverloadResolver {
@NotNull
public OverloadDomain getOverloadDomain(JetType receiverType, @NotNull JetScope outerScope, @NotNull String name) {
// TODO : extension lookup
JetScope scope = receiverType == null ? outerScope : receiverType.getMemberScope();
JetScope scope = receiverType == null ? outerScope : new ScopeWithReceiver(outerScope, receiverType, typeChecker);
final FunctionGroup functionGroup = scope.getFunctionGroup(name);
@@ -1,8 +1,11 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.base.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeChecker;
/**
* @author abreslav
@@ -11,16 +14,33 @@ public class ScopeWithReceiver extends JetScopeImpl {
private final JetScope receiverTypeScope;
private final JetScope outerScope;
private final JetTypeChecker typeChecker;
public ScopeWithReceiver(JetScope outerScope, JetType receiverType) {
public ScopeWithReceiver(JetScope outerScope, JetType receiverType, JetTypeChecker typeChecker) {
this.outerScope = outerScope;
this.receiverTypeScope = receiverType.getMemberScope();
this.typeChecker = typeChecker;
}
@NotNull
@Override
public FunctionGroup getFunctionGroup(@NotNull String name) {
return receiverTypeScope.getFunctionGroup(name); // TODO
FunctionGroup functionGroup = receiverTypeScope.getFunctionGroup(name);
if (functionGroup.isEmpty()) {
return FunctionDescriptorUtil.filteredFunctionGroup(outerScope.getFunctionGroup(name),
new Function<FunctionDescriptor, Boolean>() {
@Override
public Boolean apply(@Nullable FunctionDescriptor functionDescriptor) {
if (functionDescriptor == null) return false;
JetType functionReceiverType = functionDescriptor.getReceiverType();
if (functionReceiverType == null) {
return false;
}
return typeChecker.isSubtypeOf(receiverTypeScope.getThisType(), functionReceiverType);
}
});
}
return functionGroup; // TODO
}
@Override
@@ -249,6 +249,7 @@ public class JavaDescriptorResolver {
methodName
);
functionDescriptor.initialize(
null,
resolveTypeParameters(method.getTypeParameters()),
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptor, parameters),
semanticServices.getTypeTransformer().transformToType(method.getReturnType())
@@ -105,6 +105,7 @@ public class ErrorUtils {
private static FunctionDescriptor createErrorFunction(List<TypeParameterDescriptor> typeParameters, List<JetType> positionedValueArgumentTypes) {
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>");
return functionDescriptor.initialize(
null,
typeParameters,
getValueParameters(functionDescriptor, positionedValueArgumentTypes),
createErrorType("<ERROR FUNCTION RETURN>")
@@ -117,6 +118,7 @@ public class ErrorUtils {
private static FunctionDescriptor createErrorFunction(int typeParameterCount, List<JetType> positionedValueParameterTypes) {
return new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>").initialize(
null,
Collections.<TypeParameterDescriptor>emptyList(), // TODO
Collections.<ValueParameterDescriptor>emptyList(), // TODO
createErrorType("<ERROR FUNCTION RETURN TYPE>")
@@ -1002,7 +1002,7 @@ public class JetTypeInferrer {
public void visitWhenConditionCall(JetWhenConditionCall condition) {
checkNullSafety(finalSubjectType, condition.getOperationTokenNode());
JetExpression callSuffixExpression = condition.getCallSuffixExpression();
JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType);
JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType, semanticServices.getTypeChecker());
if (callSuffixExpression != null) {
JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false);
ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression");
@@ -1290,11 +1290,12 @@ public class JetTypeInferrer {
@Override
public void visitQualifiedExpression(JetQualifiedExpression expression) {
// TODO : functions
// TODO : functions as values
JetExpression selectorExpression = expression.getSelectorExpression();
JetExpression receiverExpression = expression.getReceiverExpression();
JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression);
if (receiverType != null) {
// TODO : extensions to 'Any?'
checkNullSafety(receiverType, expression.getOperationTokenNode());
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
if (expression.getOperationSign() == JetTokens.QUEST) {
@@ -1314,7 +1315,7 @@ public class JetTypeInferrer {
}
private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) {
JetScope compositeScope = new ScopeWithReceiver(scope, receiverType);
JetScope compositeScope = new ScopeWithReceiver(scope, receiverType, semanticServices.getTypeChecker());
if (selectorExpression instanceof JetCallExpression) {
JetCallExpression callExpression = (JetCallExpression) selectorExpression;
OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
@@ -46,6 +46,17 @@ public class DescriptorRenderer {
protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) {
stringBuilder.append(descriptor.getName());
}
@Override
public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) {
renderTypeParameter(descriptor, builder);
return null;
}
@Override
public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) {
return super.visitVariableDescriptor(descriptor, builder);
}
};
private DescriptorRenderer() {}
@@ -106,9 +117,18 @@ public class DescriptorRenderer {
@Override
public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) {
builder.append(renderKeyword("fun")).append(" ");
renderName(descriptor, builder);
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters();
renderTypeParameters(typeParameters, builder);
if (!typeParameters.isEmpty()) {
builder.append(" ");
}
JetType receiverType = descriptor.getReceiverType();
if (receiverType != null) {
builder.append(escape(receiverType.toString())).append(".");
}
renderName(descriptor, builder);
builder.append("(");
for (Iterator<ValueParameterDescriptor> iterator = descriptor.getUnsubstitutedValueParameters().iterator(); iterator.hasNext(); ) {
ValueParameterDescriptor parameterDescriptor = iterator.next();
@@ -178,7 +198,7 @@ public class DescriptorRenderer {
stringBuilder.append(escape(descriptor.getName()));
}
private void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
protected void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
renderName(descriptor, builder);
if (!descriptor.getUpperBounds().isEmpty()) {
JetType bound = descriptor.getUpperBounds().iterator().next();
@@ -0,0 +1,21 @@
fun <~T~T, ~E~E> `T`T.foo(x : `E`E, y : `A`A) : `T`T {
y.`+`plus(1)
y `+`plus 1
y `+1`+ 1.0
this?.`-`minus<T>(this)
this
}
~A~class A
~+1~fun `A`A.plus(a : Any) {
1
}
~+~fun `A`A.plus(a : Int) {
1
}
~-~fun <T> T.minus(t : T) : Int = 1