new inference: ignore return type constraints during method reference conflict resolving; work around raw type received from constructor reference given on raw type to be treated as diamond

This commit is contained in:
Anna Kozlova
2015-02-18 17:18:46 +01:00
parent 37a8e56942
commit 106ba612ce
5 changed files with 17 additions and 12 deletions
@@ -1127,13 +1127,18 @@ public class InferenceSession {
if (parameters.length == functionalMethodParameters.length && !varargs || isStatic && varargs) {//static methods
if (method.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, qualifierResolveResult.getSubstitutor())) {
PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
if (method.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor)) {
//15.13.1 If ClassType is a raw type, but is not a non-static member type of a raw type,
//the candidate notional member methods are those specified in §15.9.3 for a
//class instance creation expression that uses <> to elide the type arguments to a class
initBounds(containingClass.getTypeParameters());
psiSubstitutor = PsiSubstitutor.EMPTY;
}
for (int i = 0; i < functionalMethodParameters.length; i++) {
final PsiType pType = signature.getParameterTypes()[i];
addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(getParameterType(parameters, i, qualifierResolveResult.getSubstitutor(), varargs)),
addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(getParameterType(parameters, i, psiSubstitutor, varargs)),
PsiImplUtil.normalizeWildcardTypeByPosition(pType, reference)));
}
}
@@ -111,10 +111,10 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
@NotNull
@Override
public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) {
return inferTypeArguments();
return inferTypeArguments(includeReturnConstraint);
}
private PsiSubstitutor inferTypeArguments() {
private PsiSubstitutor inferTypeArguments(boolean includeReturnConstraint) {
if (interfaceMethod == null) return substitutor;
final InferenceSession session = new InferenceSession(method.getTypeParameters(), substitutor, reference.getManager(), reference);
session.initThrowsConstraints(method);
@@ -127,7 +127,7 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
return substitutor;
}
if (interfaceMethodReturnType != PsiType.VOID && interfaceMethodReturnType != null) {
if (includeReturnConstraint && interfaceMethodReturnType != PsiType.VOID && interfaceMethodReturnType != null) {
if (method.isConstructor()) {
//todo
session.initBounds(reference, method.getContainingClass().getTypeParameters());
@@ -230,7 +230,7 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
if (!(conflict instanceof MethodCandidateInfo)) continue;
final PsiMethod psiMethod = ((MethodCandidateInfo)conflict).getElement();
final PsiSubstitutor substitutor = conflict.getSubstitutor();
final PsiSubstitutor substitutor = ((MethodCandidateInfo)conflict).getSubstitutor(false);
final PsiType[] parameterTypes = psiMethod.getSignature(substitutor).getParameterTypes();
final boolean varargs = ((MethodCandidateInfo)conflict).isVarargs();
@@ -39,6 +39,6 @@ class MyTest1 {
static void foo(I3 i) {}
static {
foo<error descr="Cannot resolve method 'foo(<method reference>)'">(Foo::new)</error>;
foo<error descr="Ambiguous method call: both 'MyTest1.foo(I1)' and 'MyTest1.foo(I2)' match">(Foo::new)</error>;
}
}
@@ -67,7 +67,7 @@ class MyTest1 {
}
public static void main(String[] args) {
m<error descr="Ambiguous method call: both 'MyTest1.m(I2)' and 'MyTest1.m(I3)' match">(Foo::new)</error>;
m<error descr="Ambiguous method call: both 'MyTest1.m(I1)' and 'MyTest1.m(I2)' match">(Foo::new)</error>;
}
}
class MyTest2 {
@@ -104,6 +104,6 @@ class MyTest2 {
}
public static void main(String[] args) {
m<error descr="Ambiguous method call: both 'MyTest2.m(I2)' and 'MyTest2.m(I3)' match">(Foo::new)</error>;
m<error descr="Ambiguous method call: both 'MyTest2.m(I1)' and 'MyTest2.m(I2)' match">(Foo::new)</error>;
}
}
@@ -29,10 +29,10 @@ class Test {
static void meth4(I3 s) { }
static {
meth1(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
meth1(<error descr="Inferred type 'java.lang.String' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Foo::new</error>);
meth2(Foo::new);
meth3(Foo::<error descr="Cannot resolve constructor 'Foo'">new</error>);
meth4<error descr="Cannot resolve method 'meth4(<method reference>)'">(Foo::new)</error>;
meth3(<error descr="Inferred type 'java.lang.Object' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Foo::new</error>);
meth4<error descr="Ambiguous method call: both 'Test.meth4(I1)' and 'Test.meth4(I2)' match">(Foo::new)</error>;
meth1(<error descr="Inferred type 'java.lang.String' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Test::foo</error>);
meth2(Test::foo);