diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index da4de94a4a37..9120611f4072 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -265,8 +265,8 @@ public class GenericsHighlightUtil { } final PsiClassType[] bounds = classParameter.getSuperTypes(); - for (PsiClassType type1 : bounds) { - PsiType bound = substitutor.substitute(type1); + for (PsiType bound : bounds) { + bound = substitutor.substitute(bound); if (!bound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) && GenericsUtil.checkNotInBounds(type, bound, referenceParameterList)) { PsiClass boundClass = bound instanceof PsiClassType ? ((PsiClassType)bound).resolve() : null; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaClassSupersImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaClassSupersImpl.java index cb6f80275021..ccb1b9e813ec 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaClassSupersImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaClassSupersImpl.java @@ -129,7 +129,12 @@ public class JavaClassSupersImpl extends JavaClassSupers { Map innerMap = inner.getSubstitutionMap(); for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(onClass)) { if (outerMap.containsKey(parameter) || innerMap.containsKey(parameter)) { - answer = answer.put(parameter, outer.substitute(inner.substitute(parameter))); + PsiType innerType = inner.substitute(parameter); + PsiClass paramCandidate = PsiCapturedWildcardType.isCapture() ? PsiUtil.resolveClassInClassTypeOnly(innerType) : null; + PsiType targetType = paramCandidate instanceof PsiTypeParameter && paramCandidate != parameter + ? outer.substituteWithBoundsPromotion((PsiTypeParameter)paramCandidate) + : outer.substitute(innerType); + answer = answer.put(parameter, targetType); } } return answer; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/RecursiveParamBoundsWhenSuperSubstitution.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/RecursiveParamBoundsWhenSuperSubstitution.java new file mode 100644 index 000000000000..94cabdf16d16 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/RecursiveParamBoundsWhenSuperSubstitution.java @@ -0,0 +1,12 @@ +class P> { } + +class MM> { + H last; + + void m(final Function, P> function) { + generate(last, function); + } + public static void generate(E first, Function generator) { } + +} +interface Function {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/NestedWildcardsWithImplicitBounds.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/NestedWildcardsWithImplicitBounds.java new file mode 100644 index 000000000000..a04073430230 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/NestedWildcardsWithImplicitBounds.java @@ -0,0 +1,9 @@ + +import java.io.Serializable; +import java.util.List; + +interface Child extends List { + default void m(List> l) { + List> ll = l; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/GenericsHighlightingTest.java index 9d6fba2e6352..c69bf2b82fdf 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/GenericsHighlightingTest.java @@ -425,4 +425,5 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testUncheckedWarningWhenCastingFromCapturedWildcard() { doTest8Incompatibility(true); } public void testEnclosingRefInTopLevelClassExtendingInnerWhichExtendsItsOuter() { doTest8Incompatibility(true); } public void testGenericThrowTypes() { doTest5(false); } + public void testRecursiveParamBoundsWhenSuperSubstitution() { doTest6(false); } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GenericsHighlighting8Test.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GenericsHighlighting8Test.java index d813ee3d466e..deb7e2624db6 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GenericsHighlighting8Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GenericsHighlighting8Test.java @@ -1032,4 +1032,5 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase { } public void testBridgeMethodOverriding() { doTest(); } + public void testNestedWildcardsWithImplicitBounds() { doTest(); } }