diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java index 0e293f276224..c78ae8ec221e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java @@ -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; } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java index d49366f83d3c..b05414e7ef7e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java @@ -39,6 +39,38 @@ public class TypeEqualityConstraint implements ConstraintFormula { @Override public boolean reduce(InferenceSession session, List 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; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57439.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57439.java index 686e1817362e..765d20bb2f8d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57439.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57439.java @@ -18,14 +18,14 @@ class B extends A> { foo2(s); foo3(b); - foo3(eb); + foo3(eb); foo3(sb); - foo3(s); + foo3(s); foo4(b); foo4(eb); - foo4(sb); - foo4(s); + foo4(sb); + foo4(s); foo5(b); foo5(eb); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/SubtypingExtendsSuper.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/SubtypingExtendsSuper.java new file mode 100644 index 000000000000..1ced38b65118 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/SubtypingExtendsSuper.java @@ -0,0 +1,22 @@ +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class Sample { + + static List getList(Function function, ArrayList objects) { + return transform(objects, new ArrayList(), function); + } + + static > T transform(Iterable oldCollection, + T newCollection, + Function function) { + + return newCollection; + } + + interface Function { + Y apply(X input); + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java index 163be85c9634..035ea16b8c4d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java @@ -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); }