diff --git a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java index f6637fde49e1..ff3543a37f16 100644 --- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java @@ -120,7 +120,7 @@ public class GenericsUtil { PsiType mapping2 = subst2.substitute(parameter); if (mapping1 != null && mapping2 != null) { - substitutor = substitutor.put(parameter, getLeastContainingTypeArgument(mapping1, mapping2, compared, manager)); + substitutor = substitutor.put(parameter, getLeastContainingTypeArgument(mapping1, mapping2, compared, manager, type1.equals(mapping1) && type2.equals(mapping2) ? aSuper : null, parameter)); } else { substitutor = substitutor.put(parameter, null); @@ -150,9 +150,23 @@ public class GenericsUtil { private static PsiType getLeastContainingTypeArgument(PsiType type1, PsiType type2, Set> compared, - PsiManager manager) { + PsiManager manager, + PsiClass nestedLayer, + PsiTypeParameter parameter) { Pair types = new Pair(type1, type2); - if (compared.contains(types)) return PsiWildcardType.createUnbounded(manager); + if (compared.contains(types)) { + if (nestedLayer != null) { + PsiSubstitutor subst = PsiSubstitutor.EMPTY; + for (PsiTypeParameter param : PsiUtil.typeParametersIterable(nestedLayer)) { + subst = subst.put(param, PsiWildcardType.createUnbounded(manager)); + } + subst = subst.put(parameter, getLeastContainingTypeArgument(type1, type2, compared, manager, null, null)); + + final PsiClassType boundType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(nestedLayer, subst); + return PsiWildcardType.createExtends(manager, boundType); + } + return PsiWildcardType.createUnbounded(manager); + } compared.add(types); try { @@ -180,7 +194,7 @@ public class GenericsUtil { } } else if (type2 instanceof PsiWildcardType) { - return getLeastContainingTypeArgument(type2, type1, compared, manager); + return getLeastContainingTypeArgument(type2, type1, compared, manager, null, null); } //Done with wildcards diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java index a197bf02df7b..b201ac5aa7ae 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java @@ -8,7 +8,7 @@ class Test { } void foo() { - List> l = this.asList(String.class, Integer.class); + List> l = this.asList(String.class, Integer.class); l.size(); List objects = this.asList(new String(), new Integer(0)); objects.size(); @@ -146,7 +146,7 @@ class IDEADEV25515 { } public static final - List> SIMPLE_TYPES = + List> SIMPLE_TYPES = asList(String.class, Integer.class ,Long.class, Double.class, /*Date.class,*/ Boolean.class, Boolean.TYPE /*,String[].class */ /*,BigDecimal.class*/); @@ -179,3 +179,43 @@ public class MaximalType { class M extends MaximalType implements L{} class M2 extends MaximalType implements L{} ///////////// + + +class IDEA67676 { + interface I<T> {} + interface A extends I>{} + interface Com2 { + void foo(T t, U u); + } + interface Com1 { + void foo(T t); + } + + abstract class X { + abstract T foo(T x, T y); + + void bar(A x, A y) { + A, ? extends Com2>> f = foo(x, y); + f.hashCode(); + } + + void boo(A x, A y) { + A, ? extends Com2>> f = foo(x, y); + f.hashCode(); + } + + void baz(A x, A y) { + A>> f = foo(x, y); + f.hashCode(); + } + } + + abstract class A1 implements Com1 {} + abstract class B1 implements Com1 {} + + abstract class A2 implements Com2 {} + abstract class B2 implements Com2 {} + + abstract class A3 implements Com2 {} + abstract class B3 implements Com2 {} +} \ No newline at end of file