diff --git a/idea/src/org/jetbrains/jet/JetNodeTypes.java b/idea/src/org/jetbrains/jet/JetNodeTypes.java index 8899a0ce9c6..8df0d323733 100644 --- a/idea/src/org/jetbrains/jet/JetNodeTypes.java +++ b/idea/src/org/jetbrains/jet/JetNodeTypes.java @@ -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); diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index df9e10521d2..3d6c4d23c4c 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -828,7 +828,7 @@ public class ExpressionCodegen extends JetVisitor { else { IntrinsicMethod intrinsic = (IntrinsicMethod) callable; List args = new ArrayList(); - 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 { 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 { 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 { return false; } - private void pushMethodArguments(JetCall expression, List valueParameterTypes) { - List args = expression.getValueArguments(); + private void pushMethodArguments(JetCallElement expression, List valueParameterTypes) { + List 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 { 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 { } private void generateNewArray(JetCallExpression expression, Type type) { - List args = expression.getValueArguments(); + List args = expression.getValueArguments(); if (args.size() != 1) { throw new CompilationException("array constructor requires one value argument"); } diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index e97de80ecdc..1b334c29722 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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(); diff --git a/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java b/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java index ee82fb84c52..35be202837b 100644 --- a/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java +++ b/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java @@ -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; - } - } diff --git a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 828d5394a46..5d04a3e34c5 100644 --- a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -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); diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java index bb623b32761..93cb30a5905 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java @@ -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; diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingFunctionGroup.java b/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingFunctionGroup.java index df79659cb71..8624cca2bfa 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingFunctionGroup.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingFunctionGroup.java @@ -64,9 +64,17 @@ public class LazySubstitutingFunctionGroup implements FunctionGroup { @Override public Set 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; diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java index d4021b21a3f..12c3be36e8c 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java @@ -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 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 } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetCall.java b/idea/src/org/jetbrains/jet/lang/psi/Call.java similarity index 72% rename from idea/src/org/jetbrains/jet/lang/psi/JetCall.java rename to idea/src/org/jetbrains/jet/lang/psi/Call.java index 58a62ef1679..6813fdfdbaf 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetCall.java +++ b/idea/src/org/jetbrains/jet/lang/psi/Call.java @@ -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 getValueArguments(); + List getValueArguments(); @NotNull List getFunctionLiteralArguments(); @@ -25,6 +24,6 @@ public interface JetCall extends PsiElement { @NotNull List getTypeArguments(); - @NotNull - JetElement asElement(); + @Nullable + JetTypeArgumentList getTypeArgumentList(); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetAnnotationEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetAnnotationEntry.java index b5d430b2b89..77a4634e791 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetAnnotationEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetAnnotationEntry.java @@ -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 getValueArguments() { + public List getValueArguments() { JetValueArgumentList list = getValueArgumentList(); return list != null ? list.getArguments() : Collections.emptyList(); } @@ -62,20 +62,25 @@ public class JetAnnotationEntry extends JetElement implements JetCall { @NotNull @Override public List 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; } + } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java index 378dda09480..33cfe223c08 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java @@ -54,5 +54,4 @@ public class JetBinaryExpression extends JetExpression { public IElementType getOperationToken() { return getOperationReference().getReferencedNameElementType(); } - } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetCallElement.java b/idea/src/org/jetbrains/jet/lang/psi/JetCallElement.java new file mode 100644 index 00000000000..a9a1a38d6e0 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/psi/JetCallElement.java @@ -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 { + +} diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetCallExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetCallExpression.java index 33ae21cf505..84d08e200a4 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetCallExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetCallExpression.java @@ -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 getValueArguments() { + public List getValueArguments() { JetValueArgumentList list = getValueArgumentList(); return list != null ? list.getArguments() : Collections.emptyList(); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperCall.java b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperCall.java index 602cfcb63ab..91e9487a881 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperCall.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperCall.java @@ -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 getValueArguments() { + public List getValueArguments() { JetValueArgumentList list = getValueArgumentList(); return list != null ? list.getArguments() : Collections.emptyList(); } @@ -57,20 +57,25 @@ public class JetDelegatorToSuperCall extends JetDelegationSpecifier implements J @NotNull @Override public List 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; } + } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java index c06b8e216b1..9b5501880ce 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java @@ -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 getValueArguments() { + public List getValueArguments() { JetValueArgumentList list = getValueArgumentList(); return list != null ? list.getArguments() : Collections.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 getTypeArguments() { return Collections.emptyList(); } + @Override + public JetTypeArgumentList getTypeArgumentList() { + return null; + } + public JetReferenceExpression getThisReference() { return findChildByClass(JetThisReferenceExpression.class); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetNewExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetNewExpression.java index 62301009b10..b7edbc97ee2 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetNewExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetNewExpression.java @@ -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); // } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetValueArgument.java b/idea/src/org/jetbrains/jet/lang/psi/JetValueArgument.java index 15fada704b3..6a60a1088af 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetValueArgument.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetValueArgument.java @@ -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; + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/ValueArgument.java b/idea/src/org/jetbrains/jet/lang/psi/ValueArgument.java new file mode 100644 index 00000000000..967a27d3d6a --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/psi/ValueArgument.java @@ -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(); + +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/OverloadDomain.java b/idea/src/org/jetbrains/jet/lang/resolve/OverloadDomain.java index 5602e47c799..5d193d64afb 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/OverloadDomain.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/OverloadDomain.java @@ -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 typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { - return OverloadResolutionResult.nameNotFound(); - } - - @NotNull - @Override - public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List typeArguments, @NotNull List 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 typeArguments, - @NotNull Map 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 typeArguments, - @NotNull List positionedValueArgumentTypes); - - /** - * @return true if the domain is empty - */ - boolean isEmpty(); -} +//public interface OverloadDomain { +// +// OverloadDomain EMPTY = new OverloadDomain() { +// @NotNull +// @Override +// public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { +// return OverloadResolutionResult.nameNotFound(); +// } +// +// @NotNull +// @Override +// public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List typeArguments, @NotNull List 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 typeArguments, +// @NotNull Map 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 typeArguments, +// @NotNull List positionedValueArgumentTypes); +// +// /** +// * @return true if the domain is empty +// */ +// boolean isEmpty(); +//} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java index 432ec2cc843..dfa5eab8c44 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java @@ -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 typeArguments, @NotNull List positionedValueArgumentTypes) { - OverloadResolutionResult resolutionResult = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes); - if (!resolutionResult.isAmbiguity() && !resolutionResult.isSuccess()) return resolutionResult; - - Collection possiblyApplicableFunctions = resolutionResult.getFunctionDescriptors(); - - if (possiblyApplicableFunctions.isEmpty()) { - return OverloadResolutionResult.nameNotFound(); // TODO : it may be found, only the number of params did not match - } - - List applicable = new ArrayList(); - - 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 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 maximallySpecific = new ArrayList(); - 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 typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { - throw new UnsupportedOperationException(); // TODO - } - }; - } - - private boolean moreSpecific(FunctionDescriptor f, FunctionDescriptor g) { - List fParams = f.getValueParameters(); - List 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 typeArguments, @NotNull List positionedValueArgumentTypes) { +// OverloadResolutionResult resolutionResult = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes); +// if (!resolutionResult.isAmbiguity() && !resolutionResult.isSuccess()) return resolutionResult; +// +// Collection possiblyApplicableFunctions = resolutionResult.getFunctionDescriptors(); +// +// if (possiblyApplicableFunctions.isEmpty()) { +// return OverloadResolutionResult.nameNotFound(); // TODO : it may be found, only the number of params did not match +// } +// +// List applicable = new ArrayList(); +// +// 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 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 maximallySpecific = new ArrayList(); +// 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 typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { +// throw new UnsupportedOperationException(); // TODO +// } +// }; +// } +// +// private boolean moreSpecific(FunctionDescriptor f, FunctionDescriptor g) { +// List fParams = f.getValueParameters(); +// List 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; +// } +// +//} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java index 8790899191c..7f1cf889239 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java @@ -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; diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 182d8731119..4af559e9c8e 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -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(); diff --git a/idea/src/org/jetbrains/jet/lang/types/CallMaker.java b/idea/src/org/jetbrains/jet/lang/types/CallMaker.java new file mode 100644 index 00000000000..52f6bba710b --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/CallMaker.java @@ -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 getFunctionLiteralArguments() { + return Collections.emptyList(); + } + + @NotNull + @Override + public List getTypeArguments() { + return Collections.emptyList(); + } + + @Override + public JetTypeArgumentList getTypeArgumentList() { + return null; + } + } + + public static Call makeCallWithArguments(final JetExpression calleeExpression, final List valueArguments) { + return new CallStub() { + @Override + public JetExpression getCalleeExpression() { + return calleeExpression; + } + + @NotNull + @Override + public List getValueArguments() { + return valueArguments; + } + }; + } + + public static Call makeCall(final JetExpression calleeExpression, final List argumentExpressions) { + List 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.emptyList()); + } + + public static Call makeCall(final JetArrayAccessExpression arrayAccessExpression, final JetExpression rightHandSide) { + List arguments = Lists.newArrayList(arrayAccessExpression.getIndexExpressions()); + arguments.add(rightHandSide); + return makeCall(arrayAccessExpression, arguments); + } + +} diff --git a/idea/src/org/jetbrains/jet/lang/types/CallResolver.java b/idea/src/org/jetbrains/jet/lang/types/CallResolver.java new file mode 100644 index 00000000000..0c6f5464b0c --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/CallResolver.java @@ -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 candidates; + private final JetExpression receiver; + private final List typeArguments; + private final List valueArguments; + + protected ResolutionTask( + @NotNull Collection candidates, + @Nullable JetExpression receiver, + @NotNull List typeArguments, + @NotNull List valueArguments) { + this.candidates = candidates; + this.receiver = receiver; + this.typeArguments = typeArguments; + this.valueArguments = valueArguments; + } + + @NotNull + public Collection getCandidates() { + return candidates; + } + + @Nullable + public JetExpression getReceiver() { + return receiver; + } + + @NotNull + public List getTypeArguments() { + return typeArguments; + } + + @NotNull + public List 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 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 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 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 argumentsToParameters + ) { + Set usedParameters = Sets.newHashSet(); + + List valueParameters = candidate.getValueParameters(); + Map parameterByName = Maps.newHashMap(); + for (ValueParameterDescriptor valueParameter : valueParameters) { + parameterByName.put(valueParameter.getName(), valueParameter); + } + + List 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 successfulCandidates = Maps.newHashMap(); + Set failedCandidates = Sets.newHashSet(); + Map solutions = Maps.newHashMap(); + Map 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 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 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 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 typeArguments = new ArrayList(); + 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 parameterMap = Maps.newHashMap(); + for (ValueParameterDescriptor valueParameterDescriptor : substitutedFunctionDescriptor.getValueParameters()) { + parameterMap.put(valueParameterDescriptor.getOriginal(), valueParameterDescriptor); + } + + boolean localError = false; + for (Map.Entry 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 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 maximallySpecific = Maps.newHashMap(); + meLoop: + for (Map.Entry 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 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 fParams = f.getValueParameters(); + List 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 jetTypeArguments, List typeArguments, FunctionDescriptor functionDescriptor) { + Map context = Maps.newHashMap(); + + List 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 jetTypes) { + // TODO + return OverloadResolutionResult.nameNotFound(); + } + +} diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index e86051256b1..02435b0a01f 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -5,7 +5,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; +import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -20,14 +20,11 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; import org.jetbrains.jet.lang.resolve.constants.ErrorValue; import org.jetbrains.jet.lang.resolve.constants.StringValue; -import org.jetbrains.jet.lang.types.inference.ConstraintSystem; import org.jetbrains.jet.lexer.JetTokens; -import org.jetbrains.jet.resolve.DescriptorRenderer; import org.jetbrains.jet.util.WritableSlice; import java.util.*; -import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; import static org.jetbrains.jet.lang.resolve.BindingContext.STATEMENT; /** @@ -147,22 +144,18 @@ public class JetTypeInferrer { public class Services { private final BindingTrace trace; - private final ClassDescriptorResolver classDescriptorResolver; - private final TypeResolver typeResolver; private final CompileTimeConstantResolver compileTimeConstantResolver; - private final AnnotationResolver annotationResolver; + private final CallResolver callResolver; private final TypeInferrerVisitor typeInferrerVisitor; private final TypeInferrerVisitorWithNamespaces typeInferrerVisitorWithNamespaces; private Services(BindingTrace trace) { this.trace = trace; - this.annotationResolver = new AnnotationResolver(semanticServices, trace); - this.typeResolver = new TypeResolver(semanticServices, trace, true); - this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace); this.compileTimeConstantResolver = new CompileTimeConstantResolver(semanticServices, trace); this.typeInferrerVisitor = new TypeInferrerVisitor(); this.typeInferrerVisitorWithNamespaces = new TypeInferrerVisitorWithNamespaces(); + this.callResolver = new CallResolver(semanticServices, trace, JetTypeInferrer.this); } public TypeInferrerVisitorWithWritableScope newTypeInferrerVisitorWithWritableScope(WritableScope scope) { @@ -187,96 +180,86 @@ public class JetTypeInferrer { return typeInferrerVisitorWithNamespaces.getType(expression, new TypeInferenceContext(trace, scope, preferBlock, DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, NO_EXPECTED_TYPE)); } - @Nullable - private FunctionDescriptor lookupFunction( - @NotNull JetScope scope, - @NotNull JetReferenceExpression reference, - @NotNull String name, - @NotNull JetType receiverType, - @NotNull List argumentTypes, - boolean reportUnresolved) { - OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name); - // No generics. Guaranteed - overloadDomain = wrapForTracing(overloadDomain, reference, null, reportUnresolved); - OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.emptyList(), argumentTypes); - return resolutionResult.isSuccess() ? resolutionResult.getFunctionDescriptor() : null; - } - @NotNull private OverloadResolutionResult resolveNoParametersFunction(@NotNull JetType receiverType, @NotNull JetScope scope, @NotNull String name) { - OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name); +// OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name); // No generics. Guaranteed - return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.emptyList(), Collections.emptyList()); +// return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.emptyList(), Collections.emptyList()); + return callResolver.resolveExactSignature(scope, receiverType, name, Collections.emptyList()); } - private OverloadDomain getOverloadDomain( - @Nullable final JetType receiverType, - @NotNull final JetScope scope, - @NotNull JetExpression calleeExpression, - @Nullable PsiElement argumentList - ) { - final OverloadDomain[] result = new OverloadDomain[1]; - final JetSimpleNameExpression[] reference = new JetSimpleNameExpression[1]; - calleeExpression.accept(new JetVisitorVoid() { +// private OverloadDomain getOverloadDomain( +// @Nullable final JetType receiverType, +// @NotNull final JetScope scope, +// @NotNull JetExpression calleeExpression, +// @Nullable PsiElement argumentList +// ) { +// final OverloadDomain[] result = new OverloadDomain[1]; +// final JetSimpleNameExpression[] reference = new JetSimpleNameExpression[1]; +// calleeExpression.accept(new JetVisitorVoid() { +// +// @Override +// public void visitHashQualifiedExpression(JetHashQualifiedExpression expression) { +// // a#b -- create a domain for all overloads of b in a +// throw new UnsupportedOperationException(); // TODO +// } +// +// @Override +// public void visitPredicateExpression(JetPredicateExpression expression) { +// // overload lookup for checking, but the type is receiver's type + nullable +// throw new UnsupportedOperationException(); // TODO +// } +// +// @Override +// public void visitQualifiedExpression(JetQualifiedExpression expression) { +// trace.getErrorHandler().genericError(expression.getNode(), "Unsupported [JetTypeInferrer]"); +// +// // . or ?. +// // JetType receiverType = getType(scope, expression.getReceiverExpression(), false); +// // checkNullSafety(receiverType, expression.getOperationTokenNode()); +// // +// // JetExpression selectorExpression = expression.getSelectorExpression(); +// // if (selectorExpression instanceof JetSimpleNameExpression) { +// // JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression; +// // String referencedName = referenceExpression.getReferencedName(); +// // +// // if (receiverType != null && referencedName != null) { +// // // No generics. Guaranteed +// // result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName); +// // reference[0] = referenceExpression; +// // } +// // } else { +// // throw new UnsupportedOperationException(); // TODO +// // } +// } +// +// @Override +// public void visitSimpleNameExpression(JetSimpleNameExpression expression) { +// // a -- create a hierarchical lookup domain for this.a +// String referencedName = expression.getReferencedName(); +// if (referencedName != null) { +// // No generics. Guaranteed +// result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName); +// reference[0] = expression; +// } +// } +// +// @Override +// public void visitExpression(JetExpression expression) { +// // create a dummy domain for the type of e +// throw new UnsupportedOperationException(expression.getText()); // TODO +// } +// +// @Override +// public void visitJetElement(JetElement element) { +// trace.getErrorHandler().genericError(element.getNode(), "Unsupported in call element"); // TODO : Message +// } +// }); +// return wrapForTracing(result[0], reference[0], argumentList, true); +// } - @Override - public void visitHashQualifiedExpression(JetHashQualifiedExpression expression) { - // a#b -- create a domain for all overloads of b in a - throw new UnsupportedOperationException(); // TODO - } - - @Override - public void visitPredicateExpression(JetPredicateExpression expression) { - // overload lookup for checking, but the type is receiver's type + nullable - throw new UnsupportedOperationException(); // TODO - } - - @Override - public void visitQualifiedExpression(JetQualifiedExpression expression) { - trace.getErrorHandler().genericError(expression.getNode(), "Unsupported [JetTypeInferrer]"); - - // . or ?. - // JetType receiverType = getType(scope, expression.getReceiverExpression(), false); - // checkNullSafety(receiverType, expression.getOperationTokenNode()); - // - // JetExpression selectorExpression = expression.getSelectorExpression(); - // if (selectorExpression instanceof JetSimpleNameExpression) { - // JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression; - // String referencedName = referenceExpression.getReferencedName(); - // - // if (receiverType != null && referencedName != null) { - // // No generics. Guaranteed - // result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName); - // reference[0] = referenceExpression; - // } - // } else { - // throw new UnsupportedOperationException(); // TODO - // } - } - - @Override - public void visitSimpleNameExpression(JetSimpleNameExpression expression) { - // a -- create a hierarchical lookup domain for this.a - String referencedName = expression.getReferencedName(); - if (referencedName != null) { - // No generics. Guaranteed - result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName); - reference[0] = expression; - } - } - - @Override - public void visitExpression(JetExpression expression) { - // create a dummy domain for the type of e - throw new UnsupportedOperationException(expression.getText()); // TODO - } - - @Override - public void visitJetElement(JetElement element) { - trace.getErrorHandler().genericError(element.getNode(), "Unsupported in call element"); // TODO : Message - } - }); - return wrapForTracing(result[0], reference[0], argumentList, true); + public CallResolver getCallResolver() { + return callResolver; } private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee) { @@ -301,67 +284,67 @@ public class JetTypeInferrer { } } - private OverloadDomain wrapForTracing( - @NotNull final OverloadDomain overloadDomain, - @NotNull final JetReferenceExpression referenceExpression, - @Nullable final PsiElement argumentList, - final boolean reportErrors) { - return new OverloadDomain() { - @NotNull - @Override - public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { - OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType); - report(resolutionResult); - return resolutionResult; - } - - @NotNull - @Override - public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes) { - OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes); - report(resolutionResult); - return resolutionResult; - } - - private void report(OverloadResolutionResult resolutionResult) { - if (resolutionResult.isSuccess() || resolutionResult.singleFunction()) { - trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, resolutionResult.getFunctionDescriptor()); - } - if (reportErrors) { - switch (resolutionResult.getResultCode()) { - case NAME_NOT_FOUND: - trace.getErrorHandler().unresolvedReference(referenceExpression); - break; - case SINGLE_FUNCTION_ARGUMENT_MISMATCH: - if (argumentList != null) { - // TODO : More helpful message. NOTE: there's a separate handling for this for constructors - trace.getErrorHandler().genericError(argumentList.getNode(), "Arguments do not match " + DescriptorRenderer.TEXT.render(resolutionResult.getFunctionDescriptor())); - } - else { - trace.getErrorHandler().unresolvedReference(referenceExpression); - } - break; - case AMBIGUITY: - if (argumentList != null) { - // TODO : More helpful message. NOTE: there's a separate handling for this for constructors - trace.getErrorHandler().genericError(argumentList.getNode(), "Overload ambiguity [TODO : more helpful message]"); - } - else { - trace.getErrorHandler().unresolvedReference(referenceExpression); - } - break; - default: - // Not a success - } - } - } - - @Override - public boolean isEmpty() { - return overloadDomain.isEmpty(); - } - }; - } +// private OverloadDomain wrapForTracing( +// @NotNull final OverloadDomain overloadDomain, +// @NotNull final JetReferenceExpression referenceExpression, +// @Nullable final PsiElement argumentList, +// final boolean reportErrors) { +// return new OverloadDomain() { +// @NotNull +// @Override +// public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { +// OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType); +// report(resolutionResult); +// return resolutionResult; +// } +// +// @NotNull +// @Override +// public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes) { +// OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes); +// report(resolutionResult); +// return resolutionResult; +// } +// +// private void report(OverloadResolutionResult resolutionResult) { +// if (resolutionResult.isSuccess() || resolutionResult.singleFunction()) { +// trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, resolutionResult.getFunctionDescriptor()); +// } +// if (reportErrors) { +// switch (resolutionResult.getResultCode()) { +// case NAME_NOT_FOUND: +// trace.getErrorHandler().unresolvedReference(referenceExpression); +// break; +// case SINGLE_FUNCTION_ARGUMENT_MISMATCH: +// if (argumentList != null) { +// // TODO : More helpful message. NOTE: there's a separate handling for this for constructors +// trace.getErrorHandler().genericError(argumentList.getNode(), "Arguments do not match " + DescriptorRenderer.TEXT.render(resolutionResult.getFunctionDescriptor())); +// } +// else { +// trace.getErrorHandler().unresolvedReference(referenceExpression); +// } +// break; +// case AMBIGUITY: +// if (argumentList != null) { +// // TODO : More helpful message. NOTE: there's a separate handling for this for constructors +// trace.getErrorHandler().genericError(argumentList.getNode(), "Overload ambiguity [TODO : more helpful message]"); +// } +// else { +// trace.getErrorHandler().unresolvedReference(referenceExpression); +// } +// break; +// default: +// // Not a success +// } +// } +// } +// +// @Override +// public boolean isEmpty() { +// return overloadDomain.isEmpty(); +// } +// }; +// } public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) { checkFunctionReturnType(outerScope, function, functionDescriptor, DataFlowInfo.getEmpty()); @@ -537,452 +520,194 @@ public class JetTypeInferrer { return result; } - @Nullable - private JetType resolveCall( - @NotNull JetScope scope, - @NotNull JetCall call, - @NotNull JetType expectedType - ) { - JetExpression calleeExpression = call.getCalleeExpression(); - Collection candidates; - 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"); - } - - Map successfulCandidates = Maps.newHashMap(); - Set failedCandidates = Sets.newHashSet(); - Map solutions = Maps.newHashMap(); - Map traces = Maps.newHashMap(); - - for (FunctionDescriptor candidate : candidates) { - TemporaryBindingTrace temporaryTrace = new TemporaryBindingTrace(trace.getBindingContext()); - traces.put(candidate, temporaryTrace); - Services temporaryServices = getServices(temporaryTrace); - - temporaryTrace.record(BindingContext.REFERENCE_TARGET, functionReference, candidate); - - // Argument to parameter matching - Map argumentsToParameters = Maps.newHashMap(); - Set usedParameters = Sets.newHashSet(); - - List valueParameters = candidate.getValueParameters(); - Map parameterByName = Maps.newHashMap(); - for (ValueParameterDescriptor valueParameter : valueParameters) { - parameterByName.put(valueParameter.getName(), valueParameter); - } - - List valueArguments = call.getValueArguments(); - boolean someNamed = false; - boolean somePositioned = false; - boolean error = false; - for (int i = 0; i < valueArguments.size(); i++) { - JetValueArgument 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 { - trace.record(REFERENCE_TARGET, valueArgument.getArgumentName().getReferenceExpression(), valueParameterDescriptor); - argumentsToParameters.put(valueArgument, valueParameterDescriptor); - } - } - } - else { - somePositioned = true; - if (someNamed) { - temporaryTrace.getErrorHandler().genericError(valueArgument.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 { - ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1); - if (valueParameterDescriptor.isVararg()) { - argumentsToParameters.put(valueArgument, valueParameterDescriptor); - usedParameters.add(valueParameterDescriptor); - } - else { - trace.getErrorHandler().genericError(valueArgument.getNode(), "Too many arguments"); - } - } - } - } - } - - for (ValueParameterDescriptor valueParameter : valueParameters) { - if (!usedParameters.contains(valueParameter)) { - if (!valueParameter.hasDefaultValue()) { - trace.getErrorHandler().genericError(call.getValueArgumentList().getNode(), "No value passed for parameter " + valueParameter.getName()); - error = true; - } - } - } - - if (error) continue; - - if (call.getTypeArguments().isEmpty()) { - // Type argument inference - - ConstraintSystem constraintSystem = new ConstraintSystem(); - for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) { - constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO - } - - for (Map.Entry entry : argumentsToParameters.entrySet()) { - JetValueArgument 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); - 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()) { - successfulCandidates.put(candidate, candidate.substitute(solution.getSubstitutor())); - } - else { - temporaryTrace.getErrorHandler().genericError(calleeExpression.getNode(), "Type inference failed"); - failedCandidates.add(candidate); - } - } - else { - final List jetTypeArguments = call.getTypeArguments(); - - for (JetTypeProjection typeArgument : jetTypeArguments) { - if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) { - trace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning - } - } - - List typeArguments = new ArrayList(); - 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)); - } - } - - int typeArgCount = typeArguments.size(); - if (candidate.getTypeParameters().size() == typeArgCount) { - FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(typeArguments, candidate); - - assert substitutedFunctionDescriptor != null; - Map parameterMap = Maps.newHashMap(); - for (ValueParameterDescriptor valueParameterDescriptor : substitutedFunctionDescriptor.getValueParameters()) { - parameterMap.put(valueParameterDescriptor.getOriginal(), valueParameterDescriptor); - } - - boolean localError = false; - for (Map.Entry entry : argumentsToParameters.entrySet()) { - JetValueArgument valueArgument = entry.getKey(); - ValueParameterDescriptor valueParameterDescriptor = entry.getValue(); - - ValueParameterDescriptor substitutedParameter = parameterMap.get(valueParameterDescriptor.getOriginal()); - - 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); - } - } - } - - if (successfulCandidates.size() > 0) { - if (successfulCandidates.size() == 1) { - Map.Entry entry = successfulCandidates.entrySet().iterator().next(); - FunctionDescriptor functionDescriptor = entry.getKey(); - FunctionDescriptor result = entry.getValue(); - - TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor); - temporaryTrace.addAllMyDataTo(trace); - return result.getReturnType(); - } - else { - // TODO : Choose more specific - - StringBuilder stringBuilder = new StringBuilder(); - for (FunctionDescriptor functionDescriptor : successfulCandidates.keySet()) { - stringBuilder.append(DescriptorRenderer.HTML.render(functionDescriptor)).append("
"); - } - - trace.getErrorHandler().genericError(calleeExpression.getNode(), "Overload resolution ambiguity:
" + stringBuilder); - return null; - } - } - else { - 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.HTML.render(functionDescriptor)).append("
"); - } - - trace.getErrorHandler().genericError(calleeExpression.getNode(), "None of the following functions can be called with the arguments supplied:
" + stringBuilder); - } - return null; - } - } - - @Nullable - private JetType resolveCall( - @NotNull JetScope scope, - @NotNull OverloadDomain overloadDomain, - @NotNull JetCall call) { - // 1) ends with a name -> (scope, name) to look up - // 2) ends with something else -> just check types - - final List jetTypeArguments = call.getTypeArguments(); - - for (JetTypeProjection typeArgument : jetTypeArguments) { - if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) { - trace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning - } - } - - List typeArguments = new ArrayList(); - for (JetTypeProjection projection : jetTypeArguments) { - // TODO : check that there's no projection - JetTypeReference typeReference = projection.getTypeReference(); - if (typeReference != null) { - typeArguments.add(new TypeResolver(semanticServices, trace, true).resolveType(scope, typeReference)); - } - } - - return resolveCallWithTypeArguments(scope, overloadDomain, call, typeArguments); - } - - private JetType resolveCallWithTypeArguments(JetScope scope, OverloadDomain overloadDomain, JetCall call, List typeArguments) { - final List valueArguments = call.getValueArguments(); - - boolean someNamed = false; - for (JetValueArgument argument : valueArguments) { - if (argument.isNamed()) { - someNamed = true; - break; - } - } - - final List functionLiteralArguments = call.getFunctionLiteralArguments(); - - // TODO : must be a check - assert functionLiteralArguments.size() <= 1; - - if (someNamed) { - // TODO : check that all are named - trace.getErrorHandler().genericError(call.asElement().getNode(), "Named arguments are not supported"); // TODO - - } else { - List positionedValueArguments = new ArrayList(); - for (JetValueArgument argument : valueArguments) { - JetExpression argumentExpression = argument.getArgumentExpression(); - if (argumentExpression != null) { - positionedValueArguments.add(argumentExpression); - } - } - - positionedValueArguments.addAll(functionLiteralArguments); - - List valueArgumentTypes = new ArrayList(); - for (JetExpression valueArgument : positionedValueArguments) { - valueArgumentTypes.add(safeGetType(scope, valueArgument, false, NO_EXPECTED_TYPE)); // TODO - } - - OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, valueArgumentTypes); - if (resolutionResult.isSuccess()) { - final FunctionDescriptor functionDescriptor = resolutionResult.getFunctionDescriptor(); - - checkGenericBoundsInAFunctionCall(call.getTypeArguments(), typeArguments, functionDescriptor); - return functionDescriptor.getReturnType(); - } - } - return null; - } - - private void checkGenericBoundsInAFunctionCall(List jetTypeArguments, List typeArguments, FunctionDescriptor functionDescriptor) { - Map context = Maps.newHashMap(); - - List 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); - } - } - - @Nullable - public JetType checkTypeInitializerCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) { - JetTypeElement typeElement = typeReference.getTypeElement(); - if (typeElement instanceof JetUserType) { - JetUserType userType = (JetUserType) typeElement; - // TODO : to infer constructor parameters, one will need to - // 1) resolve a _class_ from the typeReference - // 2) rely on the overload domain of constructors of this class to infer type arguments - // For now we assume that the type arguments are provided, and thus the typeReference can be - // resolved into a valid type - JetType receiverType = typeResolver.resolveType(scope, typeReference); - DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor(); - if (declarationDescriptor instanceof ClassDescriptor) { - ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; - - for (JetTypeProjection typeProjection : userType.getTypeArguments()) { - switch (typeProjection.getProjectionKind()) { - case IN: - case OUT: - case STAR: - // TODO : Bug in the editor - trace.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments"); - break; - case NONE: - break; - } - } - - JetSimpleNameExpression referenceExpression = userType.getReferenceExpression(); - if (referenceExpression != null) { - return checkClassConstructorCall(scope, referenceExpression, classDescriptor, receiverType, call); - } - } - else { - trace.getErrorHandler().genericError(((JetElement) call).getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : review the message - } - return null; - } - else { - if (typeElement != null) { - trace.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message - } - } - return null; - } - - @Nullable - public JetType checkClassConstructorCall( - @NotNull JetScope scope, - @NotNull JetReferenceExpression referenceExpression, - @NotNull ClassDescriptor classDescriptor, - @NotNull JetType receiverType, - @NotNull JetCall call) { - // When one writes 'new Array(...)' this does not make much sense, and an instance - // of 'Array' must be created anyway. - // Thus, we should either prohibit projections in type arguments in such contexts, - // or treat them as an automatic upcast to the desired type, i.e. for the user not - // to be forced to write - // val a : Array = new Array(...) - // NOTE: Array may be a bad example here, some classes may have substantial functionality - // not involving their type parameters - // - // The code below upcasts the type automatically - FunctionGroup constructors = classDescriptor.getConstructors(); - OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(null, constructors); - JetType constructorReturnedType; - if (call instanceof JetDelegatorToThisCall) { - List typeArguments = receiverType.getArguments(); +// @Nullable +// private JetType resolveCall1( +// @NotNull JetScope scope, +// @NotNull OverloadDomain overloadDomain, +// @NotNull JetCallElement call) { +// // 1) ends with a name -> (scope, name) to look up +// // 2) ends with something else -> just check types +// +// final List jetTypeArguments = call.getTypeArguments(); +// +// for (JetTypeProjection typeArgument : jetTypeArguments) { +// if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) { +// trace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning +// } +// } +// +// List typeArguments = new ArrayList(); +// for (JetTypeProjection projection : jetTypeArguments) { +// // TODO : check that there's no projection +// JetTypeReference typeReference = projection.getTypeReference(); +// if (typeReference != null) { +// typeArguments.add(new TypeResolver(semanticServices, trace, true).resolveType(scope, typeReference)); +// } +// } +// +// return resolveCallWithTypeArguments(scope, overloadDomain, call, typeArguments); +// } - List projectionsStripped = Lists.newArrayList(); - for (TypeProjection typeArgument : typeArguments) { - projectionsStripped.add(typeArgument.getType()); - } +// private JetType resolveCallWithTypeArguments(JetScope scope, OverloadDomain overloadDomain, JetCallElement call, List typeArguments) { +// final List valueArguments = call.getValueArguments(); +// +// boolean someNamed = false; +// for (JetValueArgument argument : valueArguments) { +// if (argument.isNamed()) { +// someNamed = true; +// break; +// } +// } +// +// final List functionLiteralArguments = call.getFunctionLiteralArguments(); +// +// // TODO : must be a check +// assert functionLiteralArguments.size() <= 1; +// +// if (someNamed) { +// // TODO : check that all are named +// trace.getErrorHandler().genericError(call.getNode(), "Named arguments are not supported"); // TODO +// +// } else { +// List positionedValueArguments = new ArrayList(); +// for (JetValueArgument argument : valueArguments) { +// JetExpression argumentExpression = argument.getArgumentExpression(); +// if (argumentExpression != null) { +// positionedValueArguments.add(argumentExpression); +// } +// } +// +// positionedValueArguments.addAll(functionLiteralArguments); +// +// List valueArgumentTypes = new ArrayList(); +// for (JetExpression valueArgument : positionedValueArguments) { +// valueArgumentTypes.add(safeGetType(scope, valueArgument, false, NO_EXPECTED_TYPE)); // TODO +// } +// +// OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, valueArgumentTypes); +// if (resolutionResult.isSuccess()) { +// final FunctionDescriptor functionDescriptor = resolutionResult.getFunctionDescriptor(); +// +// callResolver.checkGenericBoundsInAFunctionCall(call.getTypeArguments(), typeArguments, functionDescriptor); +// return functionDescriptor.getReturnType(); +// } +// } +// return null; +// } - constructorReturnedType = resolveCallWithTypeArguments( - scope, - wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false), - call, projectionsStripped); - } - else { - constructorReturnedType = resolveCall( - scope, - wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false), - call); - } - if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) { - DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor(); - assert declarationDescriptor != null; - trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, declarationDescriptor); - // TODO : more helpful message - JetValueArgumentList argumentList = call.getValueArgumentList(); - final String errorMessage = "Cannot find a constructor overload for class " + classDescriptor.getName() + " with these arguments"; - if (argumentList != null) { - trace.getErrorHandler().genericError(argumentList.getNode(), errorMessage); - } - else { - trace.getErrorHandler().genericError(call.asElement().getNode(), errorMessage); - } - constructorReturnedType = receiverType; - } - // If no upcast needed: - return constructorReturnedType; - // Automatic upcast: - // result = receiverType; - } +// @Nullable +// public JetType checkTypeInitializerCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCallElement call) { +// JetTypeElement typeElement = typeReference.getTypeElement(); +// if (typeElement instanceof JetUserType) { +// JetUserType userType = (JetUserType) typeElement; +// // TODO : to infer constructor parameters, one will need to +// // 1) resolve a _class_ from the typeReference +// // 2) rely on the overload domain of constructors of this class to infer type arguments +// // For now we assume that the type arguments are provided, and thus the typeReference can be +// // resolved into a valid type +// JetType receiverType = typeResolver.resolveType(scope, typeReference); +// DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor(); +// if (declarationDescriptor instanceof ClassDescriptor) { +// ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; +// +// for (JetTypeProjection typeProjection : userType.getTypeArguments()) { +// switch (typeProjection.getProjectionKind()) { +// case IN: +// case OUT: +// case STAR: +// // TODO : Bug in the editor +// trace.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments"); +// break; +// case NONE: +// break; +// } +// } +// +// JetSimpleNameExpression referenceExpression = userType.getReferenceExpression(); +// if (referenceExpression != null) { +// return checkClassConstructorCall(scope, referenceExpression, classDescriptor, receiverType, call); +// } +// } +// else { +// trace.getErrorHandler().genericError(((JetElement) call).getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : review the message +// } +// return null; +// } +// else { +// if (typeElement != null) { +// trace.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message +// } +// } +// return null; +// } + +// @Nullable +// public JetType checkClassConstructorCall( +// @NotNull JetScope scope, +// @NotNull JetReferenceExpression referenceExpression, +// @NotNull ClassDescriptor classDescriptor, +// @NotNull JetType receiverType, +// @NotNull JetCallElement call) { +// // When one writes 'new Array(...)' this does not make much sense, and an instance +// // of 'Array' must be created anyway. +// // Thus, we should either prohibit projections in type arguments in such contexts, +// // or treat them as an automatic upcast to the desired type, i.e. for the user not +// // to be forced to write +// // val a : Array = new Array(...) +// // NOTE: Array may be a bad example here, some classes may have substantial functionality +// // not involving their type parameters +// // +// // The code below upcasts the type automatically +// +// +// FunctionGroup constructors = classDescriptor.getConstructors(); +//// OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(null, constructors); +// +// JetType constructorReturnedType; +// if (call instanceof JetDelegatorToThisCall) { +// List typeArguments = receiverType.getArguments(); +// +// List projectionsStripped = Lists.newArrayList(); +// for (TypeProjection typeArgument : typeArguments) { +// projectionsStripped.add(typeArgument.getType()); +// } +// +// constructorReturnedType = resolveCallWithTypeArguments( +// scope, +// wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false), +// call, projectionsStripped); +// } +// else { +// constructorReturnedType = callResolver.resolveCall( +// scope, call, NO_EXPECTED_TYPE); +//// wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false), +//// call); +// } +// if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) { +// DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor(); +// assert declarationDescriptor != null; +// trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, declarationDescriptor); +// // TODO : more helpful message +// JetValueArgumentList argumentList = call.getValueArgumentList(); +// final String errorMessage = "Cannot find a constructor overload for class " + classDescriptor.getName() + " with these arguments"; +// if (argumentList != null) { +// trace.getErrorHandler().genericError(argumentList.getNode(), errorMessage); +// } +// else { +// trace.getErrorHandler().genericError(call.getNode(), errorMessage); +// } +// constructorReturnedType = receiverType; +// } +// // If no upcast needed: +// return constructorReturnedType; +// +// // Automatic upcast: +// // result = receiverType; +// } //TODO private JetType enrichOutType(JetExpression expression, JetType initialType, @NotNull TypeInferenceContext context) { @@ -2478,12 +2203,14 @@ public class JetTypeInferrer { } private JetType getCallExpressionType(@Nullable JetType receiverType, @NotNull JetCallExpression callExpression, TypeInferenceContext context) { - JetExpression calleeExpression = callExpression.getCalleeExpression(); - if (calleeExpression == null) { - return null; - } - OverloadDomain overloadDomain = context.services.getOverloadDomain(receiverType, context.scope, calleeExpression, callExpression.getValueArgumentList()); - return context.services.resolveCall(context.scope, overloadDomain, callExpression); +// JetExpression calleeExpression = callExpression.getCalleeExpression(); +// if (calleeExpression == null) { +// return null; +// } +// OverloadDomain overloadDomain = context.services.getOverloadDomain(receiverType, context.scope, calleeExpression, callExpression.getValueArgumentList()); + JetScope scope = receiverType == null ? context.scope : new ScopeWithReceiver(context.scope, receiverType, JetTypeChecker.INSTANCE); + return context.services.callResolver.resolveCall(scope, callExpression, context.expectedType); +// return context.services.resolveCall(context.scope, overloadDomain, callExpression); } private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression, TypeInferenceContext context) { @@ -2538,7 +2265,15 @@ public class JetTypeInferrer { } JetType receiverType = getType(context.scope, baseExpression, false, context.replaceExpectedType(NO_EXPECTED_TYPE)); if (receiverType == null) return null; - FunctionDescriptor functionDescriptor = context.services.lookupFunction(context.scope, expression.getOperationSign(), name, receiverType, Collections.emptyList(), true); + + FunctionDescriptor functionDescriptor = context.services.callResolver.resolveCallWithGivenName( + context.scope, + CallMaker.makeCall(expression), + expression.getOperationSign(), + name, + baseExpression, + context.expectedType); + if (functionDescriptor == null) return null; JetType returnType = functionDescriptor.getReturnType(); JetType result; @@ -2576,11 +2311,11 @@ public class JetTypeInferrer { if (operationType == JetTokens.IDENTIFIER) { String referencedName = operationSign.getReferencedName(); if (referencedName != null) { - result = getTypeForBinaryCall(expression, referencedName, context.scope, true, context); + result = getTypeForBinaryCall(context.scope, referencedName, context, expression); } } else if (binaryOperationNames.containsKey(operationType)) { - result = getTypeForBinaryCall(expression, binaryOperationNames.get(operationType), context.scope, true, context); + result = getTypeForBinaryCall(context.scope, binaryOperationNames.get(operationType), context, expression); } else if (operationType == JetTokens.EQ) { result = visitAssignment(expression, context); @@ -2589,7 +2324,7 @@ public class JetTypeInferrer { result = visitAssignmentOperation(expression, context); } else if (comparisonOperations.contains(operationType)) { - JetType compareToReturnType = getTypeForBinaryCall(expression, "compareTo", context.scope, true, context); + JetType compareToReturnType = getTypeForBinaryCall(context.scope, "compareTo", context, expression); if (compareToReturnType != null) { TypeConstructor constructor = compareToReturnType.getConstructor(); JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary(); @@ -2608,9 +2343,17 @@ public class JetTypeInferrer { if (leftType != null) { JetType rightType = getType(context.scope, right, false, context); if (rightType != null) { - FunctionDescriptor equals = context.services.lookupFunction( - context.scope, operationSign, "equals", - leftType, Collections.singletonList(JetStandardClasses.getNullableAnyType()), false); + OverloadResolutionResult resolutionResult = context.services.callResolver.resolveExactSignature( + context.scope, leftType, "equals", + Collections.singletonList(JetStandardClasses.getNullableAnyType())); + FunctionDescriptor equals; + if (resolutionResult.isSuccess()) { + equals = resolutionResult.getFunctionDescriptor(); + } + else { + // TODO : Report ambiguous equals + equals = null; + } if (equals != null) { if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) { ensureNonemptyIntersectionOfOperandTypes(expression, context); @@ -2673,7 +2416,12 @@ public class JetTypeInferrer { private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right, TypeInferenceContext context) { String name = "contains"; - JetType containsType = getTypeForBinaryCall(context.scope, right, operationSign, left, name, true, context); + FunctionDescriptor functionDescriptor = context.services.callResolver.resolveCallWithGivenName( + context.scope, + CallMaker.makeCall(operationSign, Collections.singletonList(left)), + operationSign, + name, right, context.expectedType); + JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null; ensureBooleanResult(operationSign, name, containsType, context); } @@ -2748,14 +2496,20 @@ public class JetTypeInferrer { TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetExpression arrayExpression = expression.getArrayExpression(); JetType receiverType = getType(context.scope, arrayExpression, false, context); - List indexExpressions = expression.getIndexExpressions(); - List argumentTypes = getTypes(context.scope, indexExpressions, context); - if (argumentTypes == null) return null; +// List indexArguments = expression.getIndexArguments(); +// List argumentTypes = getTypes(context.scope, indexArguments, context); +// if (argumentTypes == null) return null; if (receiverType != null) { - FunctionDescriptor functionDescriptor = context.services.lookupFunction(context.scope, expression, "get", receiverType, argumentTypes, true); + FunctionDescriptor functionDescriptor = context.services.callResolver.resolveCallWithGivenName( + context.scope, + CallMaker.makeCall(expression, expression.getIndexExpressions()), + expression, + "get", + arrayExpression, + context.expectedType); if (functionDescriptor != null) { -// checkNullSafety(receiverType, expression.getIndexExpressions().get(0).getNode(), functionDescriptor); +// checkNullSafety(receiverType, expression.getIndexArguments().get(0).getNode(), functionDescriptor); return context.services.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType); } } @@ -2763,45 +2517,28 @@ public class JetTypeInferrer { } @Nullable - protected JetType getTypeForBinaryCall( - @NotNull JetBinaryExpression expression, - @NotNull String name, - @NotNull JetScope scope, - boolean reportUnresolved, - @NotNull TypeInferenceContext context) { - JetExpression left = expression.getLeft(); - JetExpression right = expression.getRight(); - if (right == null) { - return null; - } - JetSimpleNameExpression operationSign = expression.getOperationReference(); - return getTypeForBinaryCall(scope, left, operationSign, right, name, reportUnresolved, context); - } - - @Nullable - private JetType getTypeForBinaryCall( - @NotNull JetScope scope, - @NotNull JetExpression left, - @NotNull JetSimpleNameExpression operationSign, - @NotNull JetExpression right, - @NotNull String name, - boolean reportUnresolved, - @NotNull TypeInferenceContext context) { - JetType leftType = getType(scope, left, false, context); - JetType rightType = getType(scope, right, false, context); - if (leftType == null || rightType == null) { - return null; - } - FunctionDescriptor functionDescriptor = context.services.lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType), reportUnresolved); + protected JetType getTypeForBinaryCall(JetScope scope, String name, TypeInferenceContext context, JetBinaryExpression binaryExpression) { + // JetType leftType = getType(scope, left, false, context); +// JetType rightType = getType(scope, right, false, context); +// if (leftType == null || rightType == null) { +// return null; +// } + FunctionDescriptor functionDescriptor = context.services.callResolver.resolveCallWithGivenName( + scope, + CallMaker.makeCall(binaryExpression), + binaryExpression.getOperationReference(), + name, + binaryExpression.getLeft(), + context.expectedType); if (functionDescriptor != null) { - if (leftType.isNullable()) { - // TODO : better error message for '1 + nullableVar' case - context.trace.getErrorHandler().genericError(operationSign.getNode(), - "Infix call corresponds to a dot-qualified call '" + - left.getText() + "." + name + "(" + right.getText() + ")'" + - " which is not allowed on a nullable receiver '" + right.getText() + "'." + - " Use '?.'-qualified call instead"); - } +// if (leftType.isNullable()) { +// // TODO : better error message for '1 + nullableVar' case +// context.trace.getErrorHandler().genericError(operationSign.getNode(), +// "Infix call corresponds to a dot-qualified call '" + +// left.getText() + "." + name + "(" + right.getText() + ")'" + +// " which is not allowed on a nullable receiver '" + right.getText() + "'." + +// " Use '?.'-qualified call instead"); +// } return functionDescriptor.getReturnType(); } @@ -2978,11 +2715,12 @@ public class JetTypeInferrer { protected JetType visitAssignmentOperation(JetBinaryExpression expression, TypeInferenceContext context) { IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); String name = assignmentOperationNames.get(operationType); - JetType assignmentOperationType = getTypeForBinaryCall(expression, name, scope, false, context); + JetType assignmentOperationType = getTypeForBinaryCall(scope, name, context, expression); if (assignmentOperationType == null) { String counterpartName = binaryOperationNames.get(assignmentOperationCounterparts.get(operationType)); - JetType typeForBinaryCall = getTypeForBinaryCall(expression, counterpartName, scope, true, context); + + JetType typeForBinaryCall = getTypeForBinaryCall(scope, counterpartName, context, expression); if (typeForBinaryCall != null) { context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression); } @@ -3011,22 +2749,31 @@ public class JetTypeInferrer { return null; } - private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, TypeInferenceContext contextWithExpectedType) { - TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); - List argumentTypes = getTypes(scope, arrayAccessExpression.getIndexExpressions(), context); - if (argumentTypes == null) return null; - JetType rhsType = getType(scope, rightHandSide, false, context); - if (rhsType == null) return null; - argumentTypes.add(rhsType); - - JetType receiverType = getType(scope, arrayAccessExpression.getArrayExpression(), false, context); - if (receiverType == null) return null; - - // TODO : nasty hack: effort is duplicated - context.services.lookupFunction(scope, arrayAccessExpression, "set", receiverType, argumentTypes, true); - FunctionDescriptor functionDescriptor = context.services.lookupFunction(scope, operationSign, "set", receiverType, argumentTypes, true); + private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, TypeInferenceContext context) { +// TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); +// List argumentTypes = getTypes(scope, arrayAccessExpression.getIndexExpressions(), context); +// if (argumentTypes == null) return null; +// JetType rhsType = getType(scope, rightHandSide, false, context); +// if (rhsType == null) return null; +// argumentTypes.add(rhsType); +// +// JetType receiverType = getType(scope, arrayAccessExpression.getArrayExpression(), false, context); +// if (receiverType == null) return null; +// + Call call = CallMaker.makeCall(arrayAccessExpression, rightHandSide); +// // TODO : nasty hack: effort is duplicated +// context.services.callResolver.resolveCallWithGivenName( +// scope, +// call, +// operationSign, +// "set", arrayAccessExpression.getArrayExpression(), NO_EXPECTED_TYPE); + FunctionDescriptor functionDescriptor = context.services.callResolver.resolveCallWithGivenName( + scope, + call, + operationSign, + "set", arrayAccessExpression.getArrayExpression(), NO_EXPECTED_TYPE); if (functionDescriptor == null) return null; - return context.services.checkType(functionDescriptor.getReturnType(), arrayAccessExpression, contextWithExpectedType); + return context.services.checkType(functionDescriptor.getReturnType(), arrayAccessExpression, context); } @Override diff --git a/idea/src/org/jetbrains/jet/lang/types/inference/ConstraintSystem.java b/idea/src/org/jetbrains/jet/lang/types/inference/ConstraintSystem.java index 7e42f7d2939..d6cdb5ec09b 100644 --- a/idea/src/org/jetbrains/jet/lang/types/inference/ConstraintSystem.java +++ b/idea/src/org/jetbrains/jet/lang/types/inference/ConstraintSystem.java @@ -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);