type equality constraint: reject type/wildcard pairs; subtyping constraint: become eq constraint for types

This commit is contained in:
Anna Kozlova
2014-01-31 21:41:19 +04:00
parent 948e76acf5
commit be84252e83
5 changed files with 87 additions and 41 deletions
@@ -15,7 +15,11 @@
*/
package com.intellij.psi.impl.source.resolve.graphInference.constraints;
import com.intellij.psi.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiCapturedWildcardType;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiWildcardType;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceBound;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
@@ -23,6 +27,8 @@ import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
import java.util.List;
public class SubtypingConstraint implements ConstraintFormula {
private static final Logger LOG = Logger.getInstance("#" + SubtypingConstraint.class.getName());
private PsiType myS;
private PsiType myT;
@@ -72,13 +78,10 @@ public class SubtypingConstraint implements ConstraintFormula {
}
if (((PsiWildcardType)myT).isExtends()) {
if (tBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
return true;
}
if (myS instanceof PsiWildcardType) {
final PsiType sBound = ((PsiWildcardType)myS).getBound();
if (sBound == null) {
constraints.add(new StrictSubtypingConstraint(tBound, ((PsiWildcardType)myS).getExtendsBound()));
return true;
}
@@ -86,12 +89,21 @@ public class SubtypingConstraint implements ConstraintFormula {
constraints.add(new StrictSubtypingConstraint(tBound, sBound));
return true;
}
} else {
if (((PsiWildcardType)myS).isSuper()) {
constraints.add(new TypeEqualityConstraint(tBound, PsiType.getJavaLangObject(((PsiWildcardType)myT).getManager(), myT.getResolveScope())));
return true;
}
assert false;
}
else {
constraints.add(new StrictSubtypingConstraint(tBound, myS));
return true;
}
return false;
} else {
}
else {
LOG.assertTrue(((PsiWildcardType)myT).isSuper());
if (myS instanceof PsiWildcardType) {
final PsiType sBound = ((PsiWildcardType)myS).getBound();
@@ -120,8 +132,11 @@ public class SubtypingConstraint implements ConstraintFormula {
inferenceVariable.addBound(myS, InferenceBound.EQ);
return true;
}
constraints.add(new StrictSubtypingConstraint(myT, myS));
return true;
if (myT != null && myS != null) {
constraints.add(new TypeEqualityConstraint(myT, myS));
return true;
}
return false;
}
}
}
@@ -39,6 +39,38 @@ public class TypeEqualityConstraint implements ConstraintFormula {
@Override
public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
if (myT instanceof PsiWildcardType && myS instanceof PsiWildcardType) {
final PsiType tBound = ((PsiWildcardType)myT).getBound();
final PsiType sBound = ((PsiWildcardType)myS).getBound();
if (tBound == null && sBound == null) return true;
if (sBound == null && ((PsiWildcardType)myT).isExtends()) {
//extends bound of "?" (Object)
constraints.add(new TypeEqualityConstraint(((PsiWildcardType)myS).getExtendsBound(), tBound));
return true;
}
if (tBound == null && ((PsiWildcardType)myS).isExtends()) {
//extends bound of "?" (Object)
constraints.add(new TypeEqualityConstraint(((PsiWildcardType)myT).getExtendsBound(), sBound));
return true;
}
if (((PsiWildcardType)myT).isExtends() && ((PsiWildcardType)myS).isExtends() ||
((PsiWildcardType)myT).isSuper() && ((PsiWildcardType)myS).isSuper()) {
LOG.assertTrue(tBound != null);
LOG.assertTrue(sBound != null);
constraints.add(new TypeEqualityConstraint(tBound, sBound));
return true;
}
}
if (myT instanceof PsiWildcardType || myS instanceof PsiWildcardType) {
return false;
}
if (session.isProperType(myT) && session.isProperType(myS)) {
return myT.equals(myS);
}
@@ -75,33 +107,6 @@ public class TypeEqualityConstraint implements ConstraintFormula {
return true;
}
if (myT instanceof PsiWildcardType && myS instanceof PsiWildcardType) {
final PsiType tBound = ((PsiWildcardType)myT).getBound();
final PsiType sBound = ((PsiWildcardType)myS).getBound();
if (tBound == null && sBound == null) return true;
if (sBound == null && ((PsiWildcardType)myT).isExtends()) {
//extends bound of "?" (Object)
constraints.add(new TypeEqualityConstraint(((PsiWildcardType)myS).getExtendsBound(), tBound));
return true;
}
if (tBound == null && ((PsiWildcardType)myS).isExtends()) {
//extends bound of "?" (Object)
constraints.add(new TypeEqualityConstraint(((PsiWildcardType)myT).getExtendsBound(), sBound));
return true;
}
if (((PsiWildcardType)myT).isExtends() && ((PsiWildcardType)myS).isExtends() ||
((PsiWildcardType)myT).isSuper() && ((PsiWildcardType)myS).isSuper()) {
LOG.assertTrue(tBound != null);
LOG.assertTrue(sBound != null);
constraints.add(new TypeEqualityConstraint(tBound, sBound));
return true;
}
}
return false;
}
@@ -18,14 +18,14 @@ class B<T> extends A<A<T>> {
foo2(s);
foo3<error descr="'foo3(A<A<?>>)' in 'B' cannot be applied to '(B<capture<?>>)'">(b)</error>;
foo3<error descr="'foo3(A<A<? extends java.lang.String>>)' in 'B' cannot be applied to '(B<capture<? extends java.lang.String>>)'">(eb)</error>;
foo3<error descr="'foo3(A<A<?>>)' in 'B' cannot be applied to '(B<capture<? extends java.lang.String>>)'">(eb)</error>;
foo3<error descr="'foo3(A<A<?>>)' in 'B' cannot be applied to '(B<capture<? super java.lang.String>>)'">(sb)</error>;
foo3<error descr="'foo3(A<A<? extends java.lang.String>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
foo3<error descr="'foo3(A<A<?>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
foo4<error descr="'foo4(A<A<? super java.lang.Object>>)' in 'B' cannot be applied to '(B<capture<?>>)'">(b)</error>;
foo4<error descr="'foo4(A<A<? super java.lang.Object>>)' in 'B' cannot be applied to '(B<capture<? extends java.lang.String>>)'">(eb)</error>;
foo4<error descr="'foo4(A<A<? super java.lang.String>>)' in 'B' cannot be applied to '(B<capture<? super java.lang.String>>)'">(sb)</error>;
foo4<error descr="'foo4(A<A<? super java.lang.String>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
foo4<error descr="'foo4(A<A<? super java.lang.Object>>)' in 'B' cannot be applied to '(B<capture<? super java.lang.String>>)'">(sb)</error>;
foo4<error descr="'foo4(A<A<? super java.lang.Object>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
foo5(b);
foo5(eb);
@@ -0,0 +1,22 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class Sample {
static List<String> getList(Function<Object, String> function, ArrayList<? super String> objects) {
return transform(objects, new ArrayList<String>(), function);
}
static <R, S, T extends Collection<S>> T transform(Iterable<? extends R> oldCollection,
T newCollection,
Function<R, S> function) {
return newCollection;
}
interface Function<X, Y> {
Y apply(X input);
}
}
@@ -42,6 +42,10 @@ public class ConstraintsInferenceMiscTest extends LightDaemonAnalyzerTestCase {
doTest(false);
}
public void testSubtypingExtendsSuper() throws Exception {
doTest(false);
}
private void doTest(final boolean checkWarnings) {
doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, false);
}