Overload resolution is factored out as an independent module CallResolver.java
This commit is contained in:
@@ -117,10 +117,10 @@ public interface JetNodeTypes {
|
||||
JetNodeType CALL_EXPRESSION = new JetNodeType("CALL_EXPRESSION", JetCallExpression.class);
|
||||
JetNodeType ARRAY_ACCESS_EXPRESSION = new JetNodeType("ARRAY_ACCESS_EXPRESSION", JetArrayAccessExpression.class);
|
||||
JetNodeType INDICES = new JetNodeType("INDICES", JetContainerNode.class);
|
||||
JetNodeType DOT_QUALIFIED_EXPRESSION = new JetNodeType("DOT_QUALIFIED_EXPRESSION", JetDotQualifiedExpression.class);
|
||||
JetNodeType DOT_QUALIFIED_EXPRESSION = new JetNodeType("DOT_QUALIFIED_EXPRESSION", JetDotQualifiedExpression.class);
|
||||
JetNodeType HASH_QUALIFIED_EXPRESSION = new JetNodeType("HASH_QUALIFIED_EXPRESSION", JetHashQualifiedExpression.class);
|
||||
JetNodeType SAFE_ACCESS_EXPRESSION = new JetNodeType("SAFE_ACCESS_EXPRESSION", JetSafeQualifiedExpression.class);
|
||||
JetNodeType PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
|
||||
JetNodeType PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
|
||||
|
||||
JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.class);
|
||||
JetNodeType ROOT_NAMESPACE = new JetNodeType("ROOT_NAMESPACE", JetRootNamespaceExpression.class);
|
||||
|
||||
@@ -828,7 +828,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
else {
|
||||
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
||||
List<JetExpression> args = new ArrayList<JetExpression>();
|
||||
for (JetValueArgument argument : expression.getValueArguments()) {
|
||||
for (ValueArgument argument : expression.getValueArguments()) {
|
||||
args.add(argument.getArgumentExpression());
|
||||
}
|
||||
return intrinsic.generate(this, v, expressionType(expression), expression, args, receiver);
|
||||
@@ -876,11 +876,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
return funDescriptor;
|
||||
}
|
||||
|
||||
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCall expression) {
|
||||
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression) {
|
||||
invokeMethodWithArguments(callableMethod, expression, StackValue.none());
|
||||
}
|
||||
|
||||
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCall expression, StackValue receiver) {
|
||||
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) {
|
||||
final Type calleeType = callableMethod.getGenerateCalleeType();
|
||||
if (calleeType != null && expression instanceof JetCallExpression) {
|
||||
gen(expression.getCalleeExpression(), calleeType);
|
||||
@@ -901,7 +901,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
callableMethod.invoke(v);
|
||||
}
|
||||
|
||||
private void setOwnerFromCall(CallableMethod callableMethod, JetCall expression) {
|
||||
private void setOwnerFromCall(CallableMethod callableMethod, JetCallElement expression) {
|
||||
if (expression.getParent() instanceof JetQualifiedExpression) {
|
||||
final JetExpression receiver = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
|
||||
JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, receiver);
|
||||
@@ -993,10 +993,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void pushMethodArguments(JetCall expression, List<Type> valueParameterTypes) {
|
||||
List<JetValueArgument> args = expression.getValueArguments();
|
||||
private void pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) {
|
||||
List<? extends ValueArgument> args = expression.getValueArguments();
|
||||
for (int i = 0, argsSize = args.size(); i < argsSize; i++) {
|
||||
JetValueArgument arg = args.get(i);
|
||||
ValueArgument arg = args.get(i);
|
||||
gen(arg.getArgumentExpression(), valueParameterTypes.get(i));
|
||||
}
|
||||
}
|
||||
@@ -1430,7 +1430,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
|
||||
private void pushTypeArguments(JetCall expression) {
|
||||
private void pushTypeArguments(JetCallElement expression) {
|
||||
for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
|
||||
pushTypeArgument(jetTypeArgument);
|
||||
}
|
||||
@@ -1458,7 +1458,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
private void generateNewArray(JetCallExpression expression, Type type) {
|
||||
List<JetValueArgument> args = expression.getValueArguments();
|
||||
List<? extends ValueArgument> args = expression.getValueArguments();
|
||||
if (args.size() != 1) {
|
||||
throw new CompilationException("array constructor requires one value argument");
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return outerDescriptor instanceof ClassDescriptor ? (ClassDescriptor) outerDescriptor : null;
|
||||
}
|
||||
|
||||
private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCall constructorCall,
|
||||
private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
|
||||
ConstructorDescriptor constructorDescriptor, boolean isJavaSuperclass,
|
||||
ConstructorFrameMap frameMap) {
|
||||
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
|
||||
|
||||
@@ -25,13 +25,11 @@ public class JetSemanticServices {
|
||||
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
private final JetTypeChecker typeChecker;
|
||||
private final OverloadResolver overloadResolver;
|
||||
private final JetControlFlowDataTraceFactory flowDataTraceFactory;
|
||||
|
||||
private JetSemanticServices(JetStandardLibrary standardLibrary, JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
this.standardLibrary = standardLibrary;
|
||||
this.typeChecker = new JetTypeChecker(standardLibrary);
|
||||
this.overloadResolver = new OverloadResolver(typeChecker);
|
||||
this.flowDataTraceFactory = flowDataTraceFactory;
|
||||
}
|
||||
|
||||
@@ -54,10 +52,4 @@ public class JetSemanticServices {
|
||||
public JetTypeChecker getTypeChecker() {
|
||||
return typeChecker;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolver getOverloadResolver() {
|
||||
return overloadResolver;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -530,8 +530,8 @@ public class JetControlFlowProcessor {
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
private void visitCall(JetCall call) {
|
||||
for (JetValueArgument argument : call.getValueArguments()) {
|
||||
private void visitCall(JetCallElement call) {
|
||||
for (ValueArgument argument : call.getValueArguments()) {
|
||||
JetExpression argumentExpression = argument.getArgumentExpression();
|
||||
if (argumentExpression != null) {
|
||||
value(argumentExpression, false, false);
|
||||
|
||||
@@ -73,13 +73,10 @@ public class FunctionDescriptorUtil {
|
||||
if (substitutedType == null) return null;
|
||||
result.add(new ValueParameterDescriptorImpl(
|
||||
substitutedDescriptor,
|
||||
i,
|
||||
unsubstitutedValueParameter,
|
||||
unsubstitutedValueParameter.getAnnotations(),
|
||||
unsubstitutedValueParameter.getName(),
|
||||
unsubstitutedValueParameter.getInType() == null ? null : substitutedType,
|
||||
substitutedType,
|
||||
unsubstitutedValueParameter.hasDefaultValue(),
|
||||
unsubstitutedValueParameter.isVararg()
|
||||
substitutedType
|
||||
));
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -64,9 +64,17 @@ public class LazySubstitutingFunctionGroup implements FunctionGroup {
|
||||
@Override
|
||||
public Set<FunctionDescriptor> getFunctionDescriptors() {
|
||||
if (functionDescriptors == null) {
|
||||
functionDescriptors = Sets.newHashSet();
|
||||
for (FunctionDescriptor descriptor : functionGroup.getFunctionDescriptors()) {
|
||||
functionDescriptors.add(descriptor.substitute(substitutor));
|
||||
if (substitutor.isEmpty()) {
|
||||
functionDescriptors = functionGroup.getFunctionDescriptors();
|
||||
}
|
||||
else {
|
||||
functionDescriptors = Sets.newHashSet();
|
||||
for (FunctionDescriptor descriptor : functionGroup.getFunctionDescriptors()) {
|
||||
FunctionDescriptor substitute = descriptor.substitute(substitutor);
|
||||
if (substitute != null) {
|
||||
functionDescriptors.add(substitute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return functionDescriptors;
|
||||
|
||||
@@ -16,6 +16,7 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
private final boolean isVararg;
|
||||
private final boolean isVar;
|
||||
private final int index;
|
||||
private final ValueParameterDescriptor original;
|
||||
|
||||
public ValueParameterDescriptorImpl(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@@ -27,6 +28,7 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
boolean hasDefaultValue,
|
||||
boolean isVararg) {
|
||||
super(containingDeclaration, annotations, name, inType, outType);
|
||||
this.original = this;
|
||||
this.index = index;
|
||||
this.hasDefaultValue = hasDefaultValue;
|
||||
this.isVararg = isVararg;
|
||||
@@ -35,17 +37,17 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
|
||||
public ValueParameterDescriptorImpl(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
int index,
|
||||
@NotNull ValueParameterDescriptor original,
|
||||
@NotNull List<AnnotationDescriptor> annotations,
|
||||
@NotNull String name,
|
||||
boolean isVar,
|
||||
boolean hasDefaultValue,
|
||||
boolean isVararg) {
|
||||
super(containingDeclaration, annotations, name, null, null);
|
||||
this.index = index;
|
||||
this.hasDefaultValue = hasDefaultValue;
|
||||
this.isVararg = isVararg;
|
||||
this.isVar = isVar;
|
||||
@Nullable JetType inType,
|
||||
@NotNull JetType outType
|
||||
) {
|
||||
super(containingDeclaration, annotations, original.getName(), inType, outType);
|
||||
this.original = original;
|
||||
this.index = original.getIndex();
|
||||
this.hasDefaultValue = original.hasDefaultValue();
|
||||
this.isVararg = original.isVararg();
|
||||
this.isVar = inType != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,12 +63,6 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
// final JetDeclaration element = getPsiElement();
|
||||
// final PsiElement parent = element.getParent();
|
||||
// if (parent instanceof JetParameterList) {
|
||||
// return ((JetParameterList) parent).getParameters().indexOf(element);
|
||||
// }
|
||||
// throw new IllegalStateException("couldn't find index for parameter");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,7 +82,13 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VariableDescriptor substitute(TypeSubstitutor substitutor) {
|
||||
public ValueParameterDescriptor getOriginal() {
|
||||
return original == this ? this : original.getOriginal();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ValueParameterDescriptor substitute(TypeSubstitutor substitutor) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -9,7 +8,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface JetCall extends PsiElement {
|
||||
public interface Call {
|
||||
@Nullable
|
||||
JetExpression getCalleeExpression();
|
||||
|
||||
@@ -17,7 +16,7 @@ public interface JetCall extends PsiElement {
|
||||
JetValueArgumentList getValueArgumentList();
|
||||
|
||||
@NotNull
|
||||
List<JetValueArgument> getValueArguments();
|
||||
List<? extends ValueArgument> getValueArguments();
|
||||
|
||||
@NotNull
|
||||
List<JetExpression> getFunctionLiteralArguments();
|
||||
@@ -25,6 +24,6 @@ public interface JetCall extends PsiElement {
|
||||
@NotNull
|
||||
List<JetTypeProjection> getTypeArguments();
|
||||
|
||||
@NotNull
|
||||
JetElement asElement();
|
||||
@Nullable
|
||||
JetTypeArgumentList getTypeArgumentList();
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JetAnnotationEntry extends JetElement implements JetCall {
|
||||
public class JetAnnotationEntry extends JetElement implements JetCallElement {
|
||||
public JetAnnotationEntry(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class JetAnnotationEntry extends JetElement implements JetCall {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetValueArgument> getValueArguments() {
|
||||
public List<? extends ValueArgument> getValueArguments() {
|
||||
JetValueArgumentList list = getValueArgumentList();
|
||||
return list != null ? list.getArguments() : Collections.<JetValueArgument>emptyList();
|
||||
}
|
||||
@@ -62,20 +62,25 @@ public class JetAnnotationEntry extends JetElement implements JetCall {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetTypeProjection> getTypeArguments() {
|
||||
JetTypeReference typeReference = getTypeReference();
|
||||
if (typeReference != null) {
|
||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||
if (typeElement instanceof JetUserType) {
|
||||
JetUserType userType = (JetUserType) typeElement;
|
||||
return userType.getTypeArguments();
|
||||
}
|
||||
JetTypeArgumentList typeArgumentList = getTypeArgumentList();
|
||||
if (typeArgumentList == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
return typeArgumentList.getArguments();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement asElement() {
|
||||
return this;
|
||||
public JetTypeArgumentList getTypeArgumentList() {
|
||||
JetTypeReference typeReference = getTypeReference();
|
||||
if (typeReference == null) {
|
||||
return null;
|
||||
}
|
||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||
if (typeElement instanceof JetUserType) {
|
||||
JetUserType userType = (JetUserType) typeElement;
|
||||
return userType.getTypeArgumentList();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,5 +54,4 @@ public class JetBinaryExpression extends JetExpression {
|
||||
public IElementType getOperationToken() {
|
||||
return getOperationReference().getReferencedNameElementType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface JetCallElement extends PsiElement, Call {
|
||||
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JetCallExpression extends JetExpression implements JetCall {
|
||||
public class JetCallExpression extends JetExpression implements JetCallElement {
|
||||
public JetCallExpression(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
@@ -49,15 +49,9 @@ public class JetCallExpression extends JetExpression implements JetCall {
|
||||
return findChildrenByType(JetNodeTypes.FUNCTION_LITERAL_EXPRESSION);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement asElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetValueArgument> getValueArguments() {
|
||||
public List<? extends ValueArgument> getValueArguments() {
|
||||
JetValueArgumentList list = getValueArgumentList();
|
||||
return list != null ? list.getArguments() : Collections.<JetValueArgument>emptyList();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JetDelegatorToSuperCall extends JetDelegationSpecifier implements JetCall {
|
||||
public class JetDelegatorToSuperCall extends JetDelegationSpecifier implements JetCallElement {
|
||||
public JetDelegatorToSuperCall(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public class JetDelegatorToSuperCall extends JetDelegationSpecifier implements J
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetValueArgument> getValueArguments() {
|
||||
public List<? extends ValueArgument> getValueArguments() {
|
||||
JetValueArgumentList list = getValueArgumentList();
|
||||
return list != null ? list.getArguments() : Collections.<JetValueArgument>emptyList();
|
||||
}
|
||||
@@ -57,20 +57,25 @@ public class JetDelegatorToSuperCall extends JetDelegationSpecifier implements J
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetTypeProjection> getTypeArguments() {
|
||||
JetTypeReference typeReference = getTypeReference();
|
||||
if (typeReference != null) {
|
||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||
if (typeElement instanceof JetUserType) {
|
||||
JetUserType userType = (JetUserType) typeElement;
|
||||
return userType.getTypeArguments();
|
||||
}
|
||||
JetTypeArgumentList typeArgumentList = getTypeArgumentList();
|
||||
if (typeArgumentList == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
return typeArgumentList.getArguments();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement asElement() {
|
||||
return this;
|
||||
public JetTypeArgumentList getTypeArgumentList() {
|
||||
JetTypeReference typeReference = getTypeReference();
|
||||
if (typeReference == null) {
|
||||
return null;
|
||||
}
|
||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||
if (typeElement instanceof JetUserType) {
|
||||
JetUserType userType = (JetUserType) typeElement;
|
||||
return userType.getTypeArgumentList();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JetDelegatorToThisCall extends JetDelegationSpecifier implements JetCall {
|
||||
public class JetDelegatorToThisCall extends JetDelegationSpecifier implements JetCallElement {
|
||||
|
||||
public JetDelegatorToThisCall(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
@@ -38,7 +38,7 @@ public class JetDelegatorToThisCall extends JetDelegationSpecifier implements Je
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetValueArgument> getValueArguments() {
|
||||
public List<? extends ValueArgument> getValueArguments() {
|
||||
JetValueArgumentList list = getValueArgumentList();
|
||||
return list != null ? list.getArguments() : Collections.<JetValueArgument>emptyList();
|
||||
}
|
||||
@@ -49,18 +49,17 @@ public class JetDelegatorToThisCall extends JetDelegationSpecifier implements Je
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement asElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetTypeProjection> getTypeArguments() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetTypeArgumentList getTypeArgumentList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JetReferenceExpression getThisReference() {
|
||||
return findChildByClass(JetThisReferenceExpression.class);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.jetbrains.jet.lang.psi;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
//public class JetNewExpression extends JetExpression implements JetCall {
|
||||
//public class JetNewExpression extends JetExpression implements JetCallElement {
|
||||
// public JetNewExpression(@NotNull ASTNode node) {
|
||||
// super(node);
|
||||
// }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
@@ -9,7 +10,7 @@ import org.jetbrains.jet.lexer.JetTokens;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JetValueArgument extends JetElement {
|
||||
public class JetValueArgument extends JetElement implements ValueArgument {
|
||||
public JetValueArgument(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
@@ -23,25 +24,36 @@ public class JetValueArgument extends JetElement {
|
||||
return visitor.visitArgument(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable @IfNotParsed
|
||||
public JetExpression getArgumentExpression() {
|
||||
return findChildByClass(JetExpression.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JetValueArgumentName getArgumentName() {
|
||||
return (JetValueArgumentName) findChildByType(JetNodeTypes.VALUE_ARGUMENT_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNamed() {
|
||||
return getArgumentName() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOut() {
|
||||
return findChildByType(JetTokens.OUT_KEYWORD) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRef() {
|
||||
return findChildByType(JetTokens.REF_KEYWORD) != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement asElement() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface ValueArgument {
|
||||
@Nullable
|
||||
@JetElement.IfNotParsed
|
||||
JetExpression getArgumentExpression();
|
||||
|
||||
@Nullable
|
||||
JetValueArgumentName getArgumentName();
|
||||
|
||||
boolean isNamed();
|
||||
|
||||
boolean isOut();
|
||||
|
||||
boolean isRef();
|
||||
|
||||
@NotNull
|
||||
PsiElement asElement();
|
||||
|
||||
}
|
||||
@@ -1,55 +1,48 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface OverloadDomain {
|
||||
|
||||
OverloadDomain EMPTY = new OverloadDomain() {
|
||||
@NotNull
|
||||
@Override
|
||||
public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return A function descriptor with NO type parameters (they are already substituted) wrapped together with a result code
|
||||
*/
|
||||
@NotNull
|
||||
OverloadResolutionResult getFunctionDescriptorForNamedArguments(
|
||||
@NotNull List<JetType> typeArguments,
|
||||
@NotNull Map<String, JetType> valueArgumentTypes,
|
||||
@Nullable JetType functionLiteralArgumentType);
|
||||
|
||||
/**
|
||||
* @return A function descriptor with NO type parameters (they are already substituted) wrapped together with a result code
|
||||
*/
|
||||
@NotNull
|
||||
OverloadResolutionResult getFunctionDescriptorForPositionedArguments(
|
||||
@NotNull List<JetType> typeArguments,
|
||||
@NotNull List<JetType> positionedValueArgumentTypes);
|
||||
|
||||
/**
|
||||
* @return true if the domain is empty
|
||||
*/
|
||||
boolean isEmpty();
|
||||
}
|
||||
//public interface OverloadDomain {
|
||||
//
|
||||
// OverloadDomain EMPTY = new OverloadDomain() {
|
||||
// @NotNull
|
||||
// @Override
|
||||
// public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
// return OverloadResolutionResult.nameNotFound();
|
||||
// }
|
||||
//
|
||||
// @NotNull
|
||||
// @Override
|
||||
// public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
// return OverloadResolutionResult.nameNotFound();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isEmpty() {
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * @return A function descriptor with NO type parameters (they are already substituted) wrapped together with a result code
|
||||
// */
|
||||
// @NotNull
|
||||
// OverloadResolutionResult getFunctionDescriptorForNamedArguments(
|
||||
// @NotNull List<JetType> typeArguments,
|
||||
// @NotNull Map<String, JetType> valueArgumentTypes,
|
||||
// @Nullable JetType functionLiteralArgumentType);
|
||||
//
|
||||
// /**
|
||||
// * @return A function descriptor with NO type parameters (they are already substituted) wrapped together with a result code
|
||||
// */
|
||||
// @NotNull
|
||||
// OverloadResolutionResult getFunctionDescriptorForPositionedArguments(
|
||||
// @NotNull List<JetType> typeArguments,
|
||||
// @NotNull List<JetType> positionedValueArgumentTypes);
|
||||
//
|
||||
// /**
|
||||
// * @return true if the domain is empty
|
||||
// */
|
||||
// boolean isEmpty();
|
||||
//}
|
||||
|
||||
@@ -1,173 +1,159 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionGroup;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class OverloadResolver {
|
||||
|
||||
private final JetTypeChecker typeChecker;
|
||||
|
||||
public OverloadResolver(JetTypeChecker typeChecker) {
|
||||
this.typeChecker = typeChecker;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadDomain getOverloadDomain(@Nullable JetType receiverType, @NotNull JetScope outerScope, @NotNull String name) {
|
||||
// TODO : extension lookup
|
||||
JetScope scope = receiverType == null ? outerScope : new ScopeWithReceiver(outerScope, receiverType, typeChecker);
|
||||
|
||||
final FunctionGroup functionGroup = scope.getFunctionGroup(name);
|
||||
|
||||
return getOverloadDomain(receiverType, functionGroup);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadDomain getOverloadDomain(@Nullable final JetType receiverType, @NotNull final FunctionGroup functionGroup) {
|
||||
if (functionGroup.isEmpty()) {
|
||||
return OverloadDomain.EMPTY;
|
||||
}
|
||||
|
||||
return new OverloadDomain() {
|
||||
@NotNull
|
||||
@Override
|
||||
public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull final List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
OverloadResolutionResult resolutionResult = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
|
||||
if (!resolutionResult.isAmbiguity() && !resolutionResult.isSuccess()) return resolutionResult;
|
||||
|
||||
Collection<FunctionDescriptor> possiblyApplicableFunctions = resolutionResult.getFunctionDescriptors();
|
||||
|
||||
if (possiblyApplicableFunctions.isEmpty()) {
|
||||
return OverloadResolutionResult.nameNotFound(); // TODO : it may be found, only the number of params did not match
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (receiverType != null) {
|
||||
// ASSERT : either the receiver in not present or we are in a scope with no top-level functions
|
||||
JetType functionReceiverType = descriptor.getReceiverType();
|
||||
if (functionReceiverType != null) {
|
||||
functionReceiverType = TypeUtils.makeNullable(functionReceiverType); // Too look things up in T for T?, and later check receiver's nullability
|
||||
if (!typeChecker.isSubtypeOf(receiverType, functionReceiverType)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (descriptor.getReceiverType() != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
|
||||
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++) {
|
||||
JetType argumentType = positionedValueArgumentTypes.get(i);
|
||||
JetType parameterType = parameters.get(i).getOutType();
|
||||
// TODO : handle vararg cases here
|
||||
if (!typeChecker.isConvertibleTo(argumentType, parameterType)) {
|
||||
continue descLoop;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// vararg
|
||||
int nonVarargs = parameters.size() - 1;
|
||||
for (int i = 0; i < nonVarargs; i++) {
|
||||
JetType argumentType = positionedValueArgumentTypes.get(i);
|
||||
JetType parameterType = parameters.get(i).getOutType();
|
||||
if (!typeChecker.isConvertibleTo(argumentType, parameterType)) {
|
||||
continue descLoop;
|
||||
}
|
||||
}
|
||||
JetType varArgType = parameters.get(nonVarargs).getOutType();
|
||||
for (int i = nonVarargs, args = positionedValueArgumentTypes.size(); i < args; i++) {
|
||||
JetType argumentType = positionedValueArgumentTypes.get(i);
|
||||
if (!typeChecker.isConvertibleTo(argumentType, varArgType)) {
|
||||
continue descLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
applicable.add(descriptor);
|
||||
}
|
||||
|
||||
if (applicable.size() == 0) {
|
||||
if (resolutionResult.singleFunction()) {
|
||||
return OverloadResolutionResult.singleFunctionArgumentMismatch(resolutionResult.getFunctionDescriptor());
|
||||
}
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
} else if (applicable.size() == 1) {
|
||||
return OverloadResolutionResult.success(applicable.get(0));
|
||||
} else {
|
||||
// TODO : varargs
|
||||
|
||||
List<FunctionDescriptor> maximallySpecific = new ArrayList<FunctionDescriptor>();
|
||||
meLoop:
|
||||
for (FunctionDescriptor me : applicable) {
|
||||
for (FunctionDescriptor other : applicable) {
|
||||
if (other == me) continue;
|
||||
if (!moreSpecific(me, other) || moreSpecific(other, me)) continue meLoop;
|
||||
}
|
||||
maximallySpecific.add(me);
|
||||
}
|
||||
if (maximallySpecific.isEmpty()) {
|
||||
return OverloadResolutionResult.ambiguity(applicable);
|
||||
}
|
||||
if (maximallySpecific.size() == 1) {
|
||||
return OverloadResolutionResult.success(maximallySpecific.get(0));
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return functionGroup.isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private boolean moreSpecific(FunctionDescriptor f, FunctionDescriptor g) {
|
||||
List<ValueParameterDescriptor> fParams = f.getValueParameters();
|
||||
List<ValueParameterDescriptor> gParams = g.getValueParameters();
|
||||
|
||||
int fSize = fParams.size();
|
||||
if (fSize != gParams.size()) return false;
|
||||
for (int i = 0; i < fSize; i++) {
|
||||
JetType fParamType = fParams.get(i).getOutType();
|
||||
JetType gParamType = gParams.get(i).getOutType();
|
||||
|
||||
// TODO : maybe isSubtypeOf is sufficient?
|
||||
if (!typeChecker.isConvertibleTo(fParamType, gParamType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
//public class OverloadResolver {
|
||||
//
|
||||
// private final JetTypeChecker typeChecker;
|
||||
//
|
||||
// public OverloadResolver(JetTypeChecker typeChecker) {
|
||||
// this.typeChecker = typeChecker;
|
||||
// }
|
||||
//
|
||||
// @NotNull
|
||||
// public OverloadDomain getOverloadDomain(@Nullable JetType receiverType, @NotNull JetScope outerScope, @NotNull String name) {
|
||||
// // TODO : extension lookup
|
||||
// JetScope scope = receiverType == null ? outerScope : new ScopeWithReceiver(outerScope, receiverType, typeChecker);
|
||||
//
|
||||
// final FunctionGroup functionGroup = scope.getFunctionGroup(name);
|
||||
//
|
||||
// return getOverloadDomain(receiverType, functionGroup);
|
||||
// }
|
||||
//
|
||||
// @NotNull
|
||||
// public OverloadDomain getOverloadDomain(@Nullable final JetType receiverType, @NotNull final FunctionGroup functionGroup) {
|
||||
// if (functionGroup.isEmpty()) {
|
||||
// return OverloadDomain.EMPTY;
|
||||
// }
|
||||
//
|
||||
// return new OverloadDomain() {
|
||||
// @NotNull
|
||||
// @Override
|
||||
// public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull final List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
// OverloadResolutionResult resolutionResult = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
|
||||
// if (!resolutionResult.isAmbiguity() && !resolutionResult.isSuccess()) return resolutionResult;
|
||||
//
|
||||
// Collection<FunctionDescriptor> possiblyApplicableFunctions = resolutionResult.getFunctionDescriptors();
|
||||
//
|
||||
// if (possiblyApplicableFunctions.isEmpty()) {
|
||||
// return OverloadResolutionResult.nameNotFound(); // TODO : it may be found, only the number of params did not match
|
||||
// }
|
||||
//
|
||||
// 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();
|
||||
//
|
||||
// if (receiverType != null) {
|
||||
// // ASSERT : either the receiver in not present or we are in a scope with no top-level functions
|
||||
// JetType functionReceiverType = descriptor.getReceiverType();
|
||||
// if (functionReceiverType != null) {
|
||||
// functionReceiverType = TypeUtils.makeNullable(functionReceiverType); // Too look things up in T for T?, and later check receiver's nullability
|
||||
// if (!typeChecker.isSubtypeOf(receiverType, functionReceiverType)) {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else if (descriptor.getReceiverType() != null) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
|
||||
// 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++) {
|
||||
// JetType argumentType = positionedValueArgumentTypes.get(i);
|
||||
// JetType parameterType = parameters.get(i).getOutType();
|
||||
// // TODO : handle vararg cases here
|
||||
// if (!typeChecker.isConvertibleTo(argumentType, parameterType)) {
|
||||
// continue descLoop;
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// // vararg
|
||||
// int nonVarargs = parameters.size() - 1;
|
||||
// for (int i = 0; i < nonVarargs; i++) {
|
||||
// JetType argumentType = positionedValueArgumentTypes.get(i);
|
||||
// JetType parameterType = parameters.get(i).getOutType();
|
||||
// if (!typeChecker.isConvertibleTo(argumentType, parameterType)) {
|
||||
// continue descLoop;
|
||||
// }
|
||||
// }
|
||||
// JetType varArgType = parameters.get(nonVarargs).getOutType();
|
||||
// for (int i = nonVarargs, args = positionedValueArgumentTypes.size(); i < args; i++) {
|
||||
// JetType argumentType = positionedValueArgumentTypes.get(i);
|
||||
// if (!typeChecker.isConvertibleTo(argumentType, varArgType)) {
|
||||
// continue descLoop;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// applicable.add(descriptor);
|
||||
// }
|
||||
//
|
||||
// if (applicable.size() == 0) {
|
||||
// if (resolutionResult.singleFunction()) {
|
||||
// return OverloadResolutionResult.singleFunctionArgumentMismatch(resolutionResult.getFunctionDescriptor());
|
||||
// }
|
||||
// return OverloadResolutionResult.nameNotFound();
|
||||
// } else if (applicable.size() == 1) {
|
||||
// return OverloadResolutionResult.success(applicable.get(0));
|
||||
// } else {
|
||||
// // TODO : varargs
|
||||
//
|
||||
// List<FunctionDescriptor> maximallySpecific = new ArrayList<FunctionDescriptor>();
|
||||
// meLoop:
|
||||
// for (FunctionDescriptor me : applicable) {
|
||||
// for (FunctionDescriptor other : applicable) {
|
||||
// if (other == me) continue;
|
||||
// if (!moreSpecific(me, other) || moreSpecific(other, me)) continue meLoop;
|
||||
// }
|
||||
// maximallySpecific.add(me);
|
||||
// }
|
||||
// if (maximallySpecific.isEmpty()) {
|
||||
// return OverloadResolutionResult.ambiguity(applicable);
|
||||
// }
|
||||
// if (maximallySpecific.size() == 1) {
|
||||
// return OverloadResolutionResult.success(maximallySpecific.get(0));
|
||||
// }
|
||||
// throw new UnsupportedOperationException();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isEmpty() {
|
||||
// return functionGroup.isEmpty();
|
||||
// }
|
||||
//
|
||||
// @NotNull
|
||||
// @Override
|
||||
// public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
// throw new UnsupportedOperationException(); // TODO
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// private boolean moreSpecific(FunctionDescriptor f, FunctionDescriptor g) {
|
||||
// List<ValueParameterDescriptor> fParams = f.getValueParameters();
|
||||
// List<ValueParameterDescriptor> gParams = g.getValueParameters();
|
||||
//
|
||||
// int fSize = fParams.size();
|
||||
// if (fSize != gParams.size()) return false;
|
||||
// for (int i = 0; i < fSize; i++) {
|
||||
// JetType fParamType = fParams.get(i).getOutType();
|
||||
// JetType gParamType = gParams.get(i).getOutType();
|
||||
//
|
||||
// // TODO : maybe isSubtypeOf is sufficient?
|
||||
// if (!typeChecker.isConvertibleTo(fParamType, gParamType)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
@@ -94,7 +94,9 @@ public class SubstitutingScope implements JetScope {
|
||||
if (allDescriptors == null) {
|
||||
allDescriptors = Sets.newHashSet();
|
||||
for (DeclarationDescriptor descriptor : workerScope.getAllDescriptors()) {
|
||||
allDescriptors.add(descriptor.substitute(substitutor));
|
||||
DeclarationDescriptor substitute = descriptor.substitute(substitutor);
|
||||
assert substitute != null;
|
||||
allDescriptors.add(substitute);
|
||||
}
|
||||
}
|
||||
return allDescriptors;
|
||||
|
||||
@@ -11,15 +11,14 @@ import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.util.WritableSlice;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
@@ -568,7 +567,7 @@ public class TopDownAnalyzer {
|
||||
JetExpression delegateExpression = specifier.getDelegateExpression();
|
||||
if (delegateExpression != null) {
|
||||
JetScope scope = scopeForConstructor == null ? descriptor.getScopeForMemberResolution() : scopeForConstructor;
|
||||
JetType type = typeInferrer.getType(scope, delegateExpression, false, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
JetType type = typeInferrer.getType(scope, delegateExpression, false, NO_EXPECTED_TYPE);
|
||||
JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
if (type != null && !semanticServices.getTypeChecker().isSubtypeOf(type, supertype)) { // TODO : Convertible?
|
||||
trace.getErrorHandler().typeMismatch(delegateExpression, supertype, type);
|
||||
@@ -581,7 +580,7 @@ public class TopDownAnalyzer {
|
||||
JetTypeReference typeReference = call.getTypeReference();
|
||||
if (typeReference != null) {
|
||||
if (descriptor.getUnsubstitutedPrimaryConstructor() != null) {
|
||||
typeInferrer.checkTypeInitializerCall(scopeForConstructor, typeReference, call);
|
||||
typeInferrer.getCallResolver().resolveCall(scopeForConstructor, call, NO_EXPECTED_TYPE);
|
||||
}
|
||||
else {
|
||||
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
||||
@@ -644,7 +643,7 @@ public class TopDownAnalyzer {
|
||||
final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true);
|
||||
JetTypeInferrer.Services typeInferrer = semanticServices.getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow
|
||||
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
|
||||
typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), true, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), true, NO_EXPECTED_TYPE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -686,7 +685,7 @@ public class TopDownAnalyzer {
|
||||
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
|
||||
JetTypeReference typeReference = call.getTypeReference();
|
||||
if (typeReference != null) {
|
||||
typeInferrerForInitializers.checkTypeInitializerCall(functionInnerScope, typeReference, call);
|
||||
typeInferrerForInitializers.getCallResolver().resolveCall(functionInnerScope, call, NO_EXPECTED_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,13 +693,14 @@ public class TopDownAnalyzer {
|
||||
public void visitDelegationToThisCall(JetDelegatorToThisCall call) {
|
||||
// TODO : check that there's no recursion in this() calls
|
||||
// TODO : check: if a this() call is present, no other initializers are allowed
|
||||
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
|
||||
typeInferrerForInitializers.checkClassConstructorCall(
|
||||
functionInnerScope,
|
||||
call.getThisReference(),
|
||||
classDescriptor,
|
||||
classDescriptor.getDefaultType(),
|
||||
call);
|
||||
// ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
|
||||
// typeInferrerForInitializers.checkClassConstructorCall(
|
||||
// functionInnerScope,
|
||||
// call.getThisReference(),
|
||||
// classDescriptor,
|
||||
// classDescriptor.getDefaultType(),
|
||||
// call);
|
||||
trace.getErrorHandler().genericError(call.getNode(), "this-calls are not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -859,7 +859,7 @@ public class TopDownAnalyzer {
|
||||
private void resolvePropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer, JetScope scope) {
|
||||
JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(property, initializer); // TODO : flow JET-15
|
||||
JetTypeInferrer.Services typeInferrer = semanticServices.getTypeInferrerServices(traceForConstructors, flowInformationProvider);
|
||||
JetType type = typeInferrer.getType(getPropertyDeclarationInnerScope(scope, propertyDescriptor), initializer, false, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
JetType type = typeInferrer.getType(getPropertyDeclarationInnerScope(scope, propertyDescriptor), initializer, false, NO_EXPECTED_TYPE);
|
||||
|
||||
JetType expectedType;
|
||||
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class CallMaker {
|
||||
|
||||
private static class ExpressionValueArgument implements ValueArgument {
|
||||
|
||||
private final JetExpression expression;
|
||||
|
||||
private ExpressionValueArgument(JetExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetExpression getArgumentExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetValueArgumentName getArgumentName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNamed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOut() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRef() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement asElement() {
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class CallStub implements Call {
|
||||
@Override
|
||||
public JetValueArgumentList getValueArgumentList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetExpression> getFunctionLiteralArguments() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetTypeProjection> getTypeArguments() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetTypeArgumentList getTypeArgumentList() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Call makeCallWithArguments(final JetExpression calleeExpression, final List<? extends ValueArgument> valueArguments) {
|
||||
return new CallStub() {
|
||||
@Override
|
||||
public JetExpression getCalleeExpression() {
|
||||
return calleeExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends ValueArgument> getValueArguments() {
|
||||
return valueArguments;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Call makeCall(final JetExpression calleeExpression, final List<JetExpression> argumentExpressions) {
|
||||
List<ExpressionValueArgument> arguments = Lists.newArrayList();
|
||||
for (JetExpression argumentExpression : argumentExpressions) {
|
||||
arguments.add(new ExpressionValueArgument(argumentExpression));
|
||||
}
|
||||
return makeCallWithArguments(calleeExpression, arguments);
|
||||
}
|
||||
|
||||
public static Call makeCall(final JetBinaryExpression expression) {
|
||||
return makeCall(expression.getOperationReference(), Collections.singletonList(expression.getRight()));
|
||||
}
|
||||
|
||||
public static Call makeCall(final JetUnaryExpression expression) {
|
||||
return makeCallWithArguments(expression.getOperationSign(), Collections.<ValueArgument>emptyList());
|
||||
}
|
||||
|
||||
public static Call makeCall(final JetArrayAccessExpression arrayAccessExpression, final JetExpression rightHandSide) {
|
||||
List<JetExpression> arguments = Lists.newArrayList(arrayAccessExpression.getIndexExpressions());
|
||||
arguments.add(rightHandSide);
|
||||
return makeCall(arrayAccessExpression, arguments);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,515 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class CallResolver {
|
||||
|
||||
private static abstract class ResolutionTask {
|
||||
private final Collection<FunctionDescriptor> candidates;
|
||||
private final JetExpression receiver;
|
||||
private final List<JetTypeProjection> typeArguments;
|
||||
private final List<? extends ValueArgument> valueArguments;
|
||||
|
||||
protected ResolutionTask(
|
||||
@NotNull Collection<FunctionDescriptor> candidates,
|
||||
@Nullable JetExpression receiver,
|
||||
@NotNull List<JetTypeProjection> typeArguments,
|
||||
@NotNull List<? extends ValueArgument> valueArguments) {
|
||||
this.candidates = candidates;
|
||||
this.receiver = receiver;
|
||||
this.typeArguments = typeArguments;
|
||||
this.valueArguments = valueArguments;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<FunctionDescriptor> getCandidates() {
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetExpression getReceiver() {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetTypeProjection> getTypeArguments() {
|
||||
return typeArguments;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<? extends ValueArgument> getValueArguments() {
|
||||
return valueArguments;
|
||||
}
|
||||
|
||||
public abstract void bindFunctionReference(@NotNull BindingTrace trace, @NotNull FunctionDescriptor functionDescriptor);
|
||||
|
||||
public abstract void reportOverallResolutionError(@NotNull BindingTrace trace, @NotNull String message);
|
||||
|
||||
public abstract void reportWrongTypeArguments(@NotNull BindingTrace trace, @NotNull String message);
|
||||
|
||||
public abstract void reportWrongValueArguments(@NotNull BindingTrace trace, @NotNull String message);
|
||||
|
||||
public abstract void reportUnresolvedFunctionReference(@NotNull BindingTrace trace);
|
||||
}
|
||||
|
||||
private final BindingTrace trace;
|
||||
private final TypeResolver typeResolver;
|
||||
private final JetTypeInferrer typeInferrer;
|
||||
private final JetSemanticServices semanticServices;
|
||||
private final ClassDescriptorResolver classDescriptorResolver;
|
||||
|
||||
public CallResolver(JetSemanticServices semanticServices, BindingTrace trace, JetTypeInferrer typeInferrer) {
|
||||
this.trace = trace;
|
||||
this.typeInferrer = typeInferrer;
|
||||
this.typeResolver = new TypeResolver(semanticServices, trace, true);
|
||||
this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
|
||||
this.semanticServices = semanticServices;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType resolveCall(
|
||||
@NotNull JetScope scope,
|
||||
@NotNull JetCallElement call,
|
||||
@NotNull JetType expectedType
|
||||
) {
|
||||
FunctionDescriptor functionDescriptor = resolveSimpleCallToFunctionDescriptor(scope, null, call, expectedType);
|
||||
return functionDescriptor == null ? null : functionDescriptor.getReturnType();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor resolveCallWithGivenName(
|
||||
@NotNull JetScope scope,
|
||||
@NotNull final Call call,
|
||||
@NotNull final JetReferenceExpression functionReference,
|
||||
@NotNull String name,
|
||||
@Nullable JetExpression receiver,
|
||||
@NotNull JetType expectedType) {
|
||||
Collection<FunctionDescriptor> candidates;
|
||||
if (receiver != null) {
|
||||
JetType type = typeInferrer.getServices(trace).getType(scope, receiver, false, NO_EXPECTED_TYPE);
|
||||
if (type == null) {
|
||||
return null; // TODO : check parameter types anyway?
|
||||
}
|
||||
// TODO : autocasts
|
||||
// TODO : nullability
|
||||
candidates = type.getMemberScope().getFunctionGroup(name).getFunctionDescriptors();
|
||||
}
|
||||
else {
|
||||
candidates = scope.getFunctionGroup(name).getFunctionDescriptors();
|
||||
}
|
||||
return resolveCallToFunctionDescriptor(scope, receiver, call, functionReference.getNode(), expectedType, candidates, functionReference);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor resolveSimpleCallToFunctionDescriptor(
|
||||
@NotNull JetScope scope,
|
||||
@Nullable JetExpression receiver,
|
||||
@NotNull final JetCallElement call,
|
||||
@NotNull JetType expectedType
|
||||
) {
|
||||
JetExpression calleeExpression = call.getCalleeExpression();
|
||||
Collection<FunctionDescriptor> candidates;
|
||||
final JetReferenceExpression functionReference;
|
||||
if (calleeExpression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
|
||||
functionReference = expression;
|
||||
candidates = scope.getFunctionGroup(expression.getReferencedName()).getFunctionDescriptors();
|
||||
}
|
||||
else if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||
JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression;
|
||||
functionReference = expression.getConstructorReferenceExpression();
|
||||
JetType constructedType = typeResolver.resolveType(scope, expression.getTypeReference());
|
||||
DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
|
||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
candidates = classDescriptor.getConstructors().getFunctionDescriptors();
|
||||
}
|
||||
else {
|
||||
trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Type argument inference not implemented");
|
||||
}
|
||||
|
||||
return resolveCallToFunctionDescriptor(scope, receiver, call, call.getNode(), expectedType, candidates, functionReference);
|
||||
}
|
||||
|
||||
|
||||
private FunctionDescriptor resolveCallToFunctionDescriptor(
|
||||
JetScope scope,
|
||||
final JetExpression receiver,
|
||||
final Call call,
|
||||
final ASTNode callNode,
|
||||
JetType expectedType,
|
||||
final Collection<FunctionDescriptor> candidates,
|
||||
final JetReferenceExpression functionReference) {
|
||||
ResolutionTask task = new ResolutionTask(candidates, receiver, call.getTypeArguments(), call.getValueArguments()) {
|
||||
@Override
|
||||
public void bindFunctionReference(@NotNull BindingTrace trace, @NotNull FunctionDescriptor functionDescriptor) {
|
||||
trace.record(BindingContext.REFERENCE_TARGET, functionReference, functionDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportOverallResolutionError(@NotNull BindingTrace trace, @NotNull String message) {
|
||||
trace.getErrorHandler().genericError(callNode, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportWrongTypeArguments(@NotNull BindingTrace trace, @NotNull String message) {
|
||||
JetTypeArgumentList typeArgumentList = call.getTypeArgumentList();
|
||||
if (typeArgumentList != null) {
|
||||
trace.getErrorHandler().genericError(typeArgumentList.getNode(), message);
|
||||
}
|
||||
else {
|
||||
reportOverallResolutionError(trace, message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportWrongValueArguments(@NotNull BindingTrace trace, @NotNull String message) {
|
||||
ASTNode node;
|
||||
|
||||
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
||||
if (valueArgumentList != null) {
|
||||
node = valueArgumentList.getNode();
|
||||
}
|
||||
else if (!call.getFunctionLiteralArguments().isEmpty()) {
|
||||
node = call.getFunctionLiteralArguments().get(0).getNode();
|
||||
}
|
||||
else {
|
||||
node = callNode;
|
||||
}
|
||||
|
||||
trace.getErrorHandler().genericError(node, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportUnresolvedFunctionReference(@NotNull BindingTrace trace) {
|
||||
trace.getErrorHandler().unresolvedReference(functionReference);
|
||||
}
|
||||
};
|
||||
return performResolution(scope, expectedType, task);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private boolean mapValueArgumentsToParameters(
|
||||
@NotNull ResolutionTask task,
|
||||
@NotNull FunctionDescriptor candidate,
|
||||
@NotNull BindingTrace temporaryTrace,
|
||||
@NotNull Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters
|
||||
) {
|
||||
Set<ValueParameterDescriptor> usedParameters = Sets.newHashSet();
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = candidate.getValueParameters();
|
||||
Map<String, ValueParameterDescriptor> parameterByName = Maps.newHashMap();
|
||||
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
||||
parameterByName.put(valueParameter.getName(), valueParameter);
|
||||
}
|
||||
|
||||
List<? extends ValueArgument> valueArguments = task.getValueArguments();
|
||||
|
||||
boolean someNamed = false;
|
||||
boolean somePositioned = false;
|
||||
boolean error = false;
|
||||
for (int i = 0; i < valueArguments.size(); i++) {
|
||||
ValueArgument valueArgument = valueArguments.get(i);
|
||||
if (valueArgument.isNamed()) {
|
||||
someNamed = true;
|
||||
if (somePositioned) {
|
||||
temporaryTrace.getErrorHandler().genericError(valueArgument.getArgumentName().getNode(), "Mixing named and positioned arguments in not allowed");
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(valueArgument.getArgumentName().getName());
|
||||
usedParameters.add(valueParameterDescriptor);
|
||||
if (valueParameterDescriptor == null) {
|
||||
temporaryTrace.getErrorHandler().genericError(valueArgument.getArgumentName().getNode(), "Cannot find a parameter with this name");
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
temporaryTrace.record(REFERENCE_TARGET, valueArgument.getArgumentName().getReferenceExpression(), valueParameterDescriptor);
|
||||
argumentsToParameters.put(valueArgument, valueParameterDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
somePositioned = true;
|
||||
if (someNamed) {
|
||||
temporaryTrace.getErrorHandler().genericError(valueArgument.asElement().getNode(), "Mixing named and positioned arguments in not allowed");
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
if (i < valueParameters.size()) {
|
||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(i);
|
||||
usedParameters.add(valueParameterDescriptor);
|
||||
argumentsToParameters.put(valueArgument, valueParameterDescriptor);
|
||||
}
|
||||
else if (!valueParameters.isEmpty()) {
|
||||
|
||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
||||
if (valueParameterDescriptor.isVararg()) {
|
||||
argumentsToParameters.put(valueArgument, valueParameterDescriptor);
|
||||
usedParameters.add(valueParameterDescriptor);
|
||||
}
|
||||
else {
|
||||
temporaryTrace.getErrorHandler().genericError(valueArgument.asElement().getNode(), "Too many arguments");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
temporaryTrace.getErrorHandler().genericError(valueArgument.asElement().getNode(), "Too many arguments");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
||||
if (!usedParameters.contains(valueParameter)) {
|
||||
if (!valueParameter.hasDefaultValue()) {
|
||||
task.reportWrongValueArguments(temporaryTrace, "No value passed for parameter " + valueParameter.getName());
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FunctionDescriptor performResolution(@NotNull JetScope scope, @NotNull JetType expectedType, @NotNull ResolutionTask task) {
|
||||
Map<FunctionDescriptor, FunctionDescriptor> successfulCandidates = Maps.newHashMap();
|
||||
Set<FunctionDescriptor> failedCandidates = Sets.newHashSet();
|
||||
Map<FunctionDescriptor, ConstraintSystem.Solution> solutions = Maps.newHashMap();
|
||||
Map<FunctionDescriptor, TemporaryBindingTrace> traces = Maps.newHashMap();
|
||||
|
||||
for (FunctionDescriptor candidate : task.getCandidates()) {
|
||||
TemporaryBindingTrace temporaryTrace = new TemporaryBindingTrace(trace.getBindingContext());
|
||||
traces.put(candidate, temporaryTrace);
|
||||
JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
|
||||
|
||||
task.bindFunctionReference(temporaryTrace, candidate);
|
||||
|
||||
Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters = Maps.newHashMap();
|
||||
boolean error = mapValueArgumentsToParameters(task, candidate, temporaryTrace, argumentsToParameters);
|
||||
|
||||
if (error) continue;
|
||||
|
||||
if (task.getTypeArguments().isEmpty()) {
|
||||
// Type argument inference
|
||||
|
||||
ConstraintSystem constraintSystem = new ConstraintSystem();
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
|
||||
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO
|
||||
}
|
||||
|
||||
for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
|
||||
ValueArgument valueArgument = entry.getKey();
|
||||
ValueParameterDescriptor valueParameterDescriptor = entry.getValue();
|
||||
|
||||
JetExpression expression = valueArgument.getArgumentExpression();
|
||||
// TODO : more attempts, with different expected types
|
||||
JetType type = temporaryServices.getType(scope, expression, false, NO_EXPECTED_TYPE);
|
||||
if (type != null) {
|
||||
constraintSystem.addSubtypingConstraint(type, valueParameterDescriptor.getOutType());
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedType != NO_EXPECTED_TYPE) {
|
||||
constraintSystem.addSubtypingConstraint(candidate.getReturnType(), expectedType);
|
||||
}
|
||||
|
||||
ConstraintSystem.Solution solution = constraintSystem.solve();
|
||||
solutions.put(candidate, solution);
|
||||
if (solution.isSuccessful()) {
|
||||
FunctionDescriptor substitute = candidate.substitute(solution.getSubstitutor());
|
||||
assert substitute != null;
|
||||
successfulCandidates.put(candidate, substitute);
|
||||
}
|
||||
else {
|
||||
task.reportOverallResolutionError(temporaryTrace, "Type inference failed");
|
||||
failedCandidates.add(candidate);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Explicit type arguments passed
|
||||
|
||||
final List<JetTypeProjection> jetTypeArguments = task.getTypeArguments();
|
||||
|
||||
for (JetTypeProjection typeArgument : jetTypeArguments) {
|
||||
if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
|
||||
temporaryTrace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
|
||||
}
|
||||
}
|
||||
|
||||
List<JetType> typeArguments = new ArrayList<JetType>();
|
||||
for (JetTypeProjection projection : jetTypeArguments) {
|
||||
// TODO : check that there's no projection
|
||||
JetTypeReference typeReference = projection.getTypeReference();
|
||||
if (typeReference != null) {
|
||||
typeArguments.add(new TypeResolver(semanticServices, temporaryTrace, true).resolveType(scope, typeReference));
|
||||
}
|
||||
}
|
||||
|
||||
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate);
|
||||
|
||||
int typeArgCount = typeArguments.size();
|
||||
if (candidate.getTypeParameters().size() == typeArgCount) {
|
||||
FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(typeArguments, candidate);
|
||||
|
||||
assert substitutedFunctionDescriptor != null;
|
||||
Map<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap = Maps.newHashMap();
|
||||
for (ValueParameterDescriptor valueParameterDescriptor : substitutedFunctionDescriptor.getValueParameters()) {
|
||||
parameterMap.put(valueParameterDescriptor.getOriginal(), valueParameterDescriptor);
|
||||
}
|
||||
|
||||
boolean localError = false;
|
||||
for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
|
||||
ValueArgument valueArgument = entry.getKey();
|
||||
ValueParameterDescriptor valueParameterDescriptor = entry.getValue();
|
||||
|
||||
ValueParameterDescriptor substitutedParameter = parameterMap.get(valueParameterDescriptor.getOriginal());
|
||||
|
||||
assert substitutedParameter != null;
|
||||
|
||||
JetType parameterType = substitutedParameter.getOutType();
|
||||
JetType type = temporaryServices.getType(scope, valueArgument.getArgumentExpression(), false, parameterType);
|
||||
if (type == null) {
|
||||
localError = true;
|
||||
}
|
||||
}
|
||||
if (localError) {
|
||||
failedCandidates.add(candidate);
|
||||
}
|
||||
else {
|
||||
successfulCandidates.put(candidate, substitutedFunctionDescriptor);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
failedCandidates.add(candidate);
|
||||
task.reportWrongTypeArguments(temporaryTrace, "Number of type arguments does not match " + DescriptorRenderer.TEXT.render(candidate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (successfulCandidates.size() > 0) {
|
||||
if (successfulCandidates.size() == 1) {
|
||||
Map.Entry<FunctionDescriptor, FunctionDescriptor> entry = successfulCandidates.entrySet().iterator().next();
|
||||
FunctionDescriptor functionDescriptor = entry.getKey();
|
||||
FunctionDescriptor result = entry.getValue();
|
||||
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
temporaryTrace.addAllMyDataTo(trace);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
Map<FunctionDescriptor, TemporaryBindingTrace> maximallySpecific = Maps.newHashMap();
|
||||
meLoop:
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> myEntry : successfulCandidates.entrySet()) {
|
||||
FunctionDescriptor me = myEntry.getValue();
|
||||
TemporaryBindingTrace myTrace = traces.get(myEntry.getKey());
|
||||
for (FunctionDescriptor other : successfulCandidates.values()) {
|
||||
if (other == me) continue;
|
||||
if (!moreSpecific(me, other) || moreSpecific(other, me)) continue meLoop;
|
||||
}
|
||||
maximallySpecific.put(me, myTrace);
|
||||
}
|
||||
if (maximallySpecific.size() == 1) {
|
||||
Map.Entry<FunctionDescriptor, TemporaryBindingTrace> result = maximallySpecific.entrySet().iterator().next();
|
||||
result.getValue().addAllMyDataTo(trace);
|
||||
return result.getKey();
|
||||
}
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (FunctionDescriptor functionDescriptor : successfulCandidates.keySet()) {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
|
||||
}
|
||||
|
||||
task.reportOverallResolutionError(trace, "Overload resolution ambiguity: " + stringBuilder);
|
||||
}
|
||||
}
|
||||
else if (!failedCandidates.isEmpty()) {
|
||||
if (failedCandidates.size() == 1) {
|
||||
FunctionDescriptor functionDescriptor = failedCandidates.iterator().next();
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
temporaryTrace.addAllMyDataTo(trace);
|
||||
}
|
||||
else {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (FunctionDescriptor functionDescriptor : failedCandidates) {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
|
||||
}
|
||||
|
||||
task.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: " + stringBuilder);
|
||||
}
|
||||
}
|
||||
else {
|
||||
task.reportUnresolvedFunctionReference(trace);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean moreSpecific(FunctionDescriptor f, FunctionDescriptor g) {
|
||||
List<ValueParameterDescriptor> fParams = f.getValueParameters();
|
||||
List<ValueParameterDescriptor> gParams = g.getValueParameters();
|
||||
|
||||
int fSize = fParams.size();
|
||||
if (fSize != gParams.size()) return false;
|
||||
for (int i = 0; i < fSize; i++) {
|
||||
JetType fParamType = fParams.get(i).getOutType();
|
||||
JetType gParamType = gParams.get(i).getOutType();
|
||||
|
||||
if (!JetTypeChecker.INSTANCE.isSubtypeOf(fParamType, gParamType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void checkGenericBoundsInAFunctionCall(List<JetTypeProjection> jetTypeArguments, List<JetType> typeArguments, FunctionDescriptor functionDescriptor) {
|
||||
Map<TypeConstructor, TypeProjection> context = Maps.newHashMap();
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getOriginal().getTypeParameters();
|
||||
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
|
||||
TypeParameterDescriptor typeParameter = typeParameters.get(i);
|
||||
JetType typeArgument = typeArguments.get(i);
|
||||
context.put(typeParameter.getTypeConstructor(), new TypeProjection(typeArgument));
|
||||
}
|
||||
TypeSubstitutor substitutor = TypeSubstitutor.create(context);
|
||||
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
|
||||
JetType typeArgument = typeArguments.get(i);
|
||||
JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference();
|
||||
assert typeReference != null;
|
||||
classDescriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolutionResult resolveExactSignature(@NotNull JetScope scope, @NotNull JetType receiver, @NotNull String name, @NotNull List<JetType> jetTypes) {
|
||||
// TODO
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -194,12 +194,12 @@ public class ConstraintSystem {
|
||||
private UnknownType getTypeVariable(TypeParameterDescriptor typeParameterDescriptor) {
|
||||
UnknownType unknownType = unknownTypes.get(typeParameterDescriptor);
|
||||
if (unknownType == null) {
|
||||
throw new IllegalArgumentException("This type parameter is not an unknown in this constraint system");
|
||||
throw new IllegalArgumentException("This type parameter is not an unknown in this constraint system: " + typeParameterDescriptor);
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
public void addSubtypingConstraint(JetType lower, JetType upper) {
|
||||
public void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper) {
|
||||
TypeValue typeValueForLower = getTypeValueFor(lower);
|
||||
TypeValue typeValueForUpper = getTypeValueFor(upper);
|
||||
addSubtypingConstraintOnTypeValues(typeValueForLower, typeValueForUpper);
|
||||
|
||||
Reference in New Issue
Block a user