take into account container class type parameters

when non-generic inner class is located inside generic outer, inference variables could be hidden in parent parameters (IDEA-174762; IDEA-174776)
This commit is contained in:
Anna Kozlova
2017-06-22 12:14:03 +03:00
parent 5621b5745e
commit cba2ff917b
5 changed files with 77 additions and 7 deletions
@@ -992,8 +992,14 @@ public class InferenceSession {
}
return false;
}
for (PsiType psiType : classType.getParameters()) {
if (!psiType.accept(this)) return false;
PsiClassType.ClassResolveResult result = classType.resolveGenerics();
PsiClass aClass = result.getElement();
if (aClass != null) {
PsiSubstitutor substitutor = result.getSubstitutor();
for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) {
PsiType psiType = substitutor.substitute(typeParameter);
if (psiType != null && !psiType.accept(this)) return false;
}
}
return true;
}
@@ -150,18 +150,19 @@ public class StrictSubtypingConstraint implements ConstraintFormula {
if (SClass == null) return false;
if (((PsiClassType)myT).isRaw()) {
return InheritanceUtil.isInheritorOrSelf(SClass, CClass, true);
}
PsiSubstitutor substitutor = SResult.getSubstitutor();
for (PsiTypeParameter typeParameter : SClass.getTypeParameters()) {
substitutor = substitutor.put(typeParameter, substitutor.substituteWithBoundsPromotion(typeParameter));
}
if (((PsiClassType)myT).isRaw()) {
return InheritanceUtil.isInheritorOrSelf(SClass, CClass, true);
}
final PsiSubstitutor tSubstitutor = TResult.getSubstitutor();
final PsiSubstitutor sSubstitutor = TypeConversionUtil.getClassSubstitutor(CClass, SClass, substitutor);
if (sSubstitutor != null) {
for (PsiTypeParameter parameter : CClass.getTypeParameters()) {
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(CClass)) {
final PsiType tSubstituted = tSubstitutor.substitute(parameter);
final PsiType sSubstituted = sSubstitutor.substitute(parameter);
if (tSubstituted == null ^ sSubstituted == null) {
@@ -21,6 +21,7 @@ import com.intellij.psi.*;
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;
import com.intellij.psi.util.PsiUtil;
import java.util.List;
@@ -98,7 +99,7 @@ public class TypeEqualityConstraint implements ConstraintFormula {
if (tClass != null && tClass.getManager().areElementsEquivalent(tClass, sResult.getElement())) {
final PsiSubstitutor tSubstitutor = tResult.getSubstitutor();
final PsiSubstitutor sSubstitutor = sResult.getSubstitutor();
for (PsiTypeParameter typeParameter : tClass.getTypeParameters()) {
for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(tClass)) {
final PsiType tSubstituted = tSubstitutor.substitute(typeParameter);
final PsiType sSubstituted = sSubstitutor.substitute(typeParameter);
if (tSubstituted != null && sSubstituted != null) {
@@ -0,0 +1,60 @@
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
class OuterClass<E> {
private class InnerClass {}
private static <T> void someMethod(OuterClass<T>.InnerClass inner) {}
static <T1> void callSomeMethod(OuterClass<T1>.InnerClass inner) {
someMethod(inner);
}
}
class Outer<T> {
public static <U> Outer<U> loopback(Outer<U>.Inner u){
return foo(u);
}
private static <T> Outer<T> foo(Outer<T>.Inner u){
return null;
}
private class Inner{}
}
class Outer1<O> {
public static <T0> void loopback(List<Outer1<T0>.Inner> u){
Outer1<T0>.Inner a = foo(u);
}
private static <T> Outer1<T>.Inner foo(List<Outer1<T>.Inner> u){
return null;
}
private class Inner {}
}
class Outer2<O> {
public static <T0> void loopback(List<? extends Outer2<T0>.Inner> u){
Outer2<? extends T0>.Inner a = foo(u);
}
private static <T> Outer2<? extends T>.Inner foo(List<? extends Outer2<T>.Inner> u){
return null;
}
private class Inner {}
}
class Outer3<O> {
{
bar(Outer3.Inner::new, new ArrayList<>());
bar(Inner::new, new ArrayList<>());
}
private <K> void bar(final Supplier<Outer3<K>.Inner> s, List<K> l) {
}
private class Inner {}
}
@@ -1013,6 +1013,8 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testNonGenericInnerOfGenericOuter() { doTest(); }
public void testTypeParameterBoundsWithSubstitutionWhenMethodHierarchyIsChecked() throws Exception {
doTest();
}