capture conversion: add upper bound for ? super if corresponding type parameter has upper bounds( IDEA-128328; IDEA-128972)

This commit is contained in:
Anna Kozlova
2014-08-27 20:59:32 +04:00
parent 66b21d3562
commit 624fa25d38
7 changed files with 65 additions and 7 deletions
@@ -28,6 +28,8 @@ public class PsiCapturedWildcardType extends PsiType.Stub {
@NotNull private final PsiElement myContext;
@Nullable private final PsiTypeParameter myParameter;
private PsiType myUpperBound;
@NotNull
public static PsiCapturedWildcardType create(@NotNull PsiWildcardType existential, @NotNull PsiElement context) {
return create(existential, context, null);
@@ -40,11 +42,28 @@ public class PsiCapturedWildcardType extends PsiType.Stub {
return new PsiCapturedWildcardType(existential, context, parameter);
}
private PsiCapturedWildcardType(@NotNull PsiWildcardType existential, @NotNull PsiElement context, @Nullable PsiTypeParameter parameter) {
private PsiCapturedWildcardType(@NotNull PsiWildcardType existential,
@NotNull PsiElement context,
@Nullable PsiTypeParameter parameter) {
super(PsiAnnotation.EMPTY_ARRAY);
myExistential = existential;
myContext = context;
myParameter = parameter;
if (parameter != null) {
final PsiClassType[] boundTypes = parameter.getExtendsListTypes();
if (boundTypes.length > 0) {
PsiType result = null;
for (PsiType type : boundTypes) {
if (result == null) {
result = type;
}
else {
result = GenericsUtil.getGreatestLowerBound(result, type);
}
}
myUpperBound = result;
}
}
}
@Override
@@ -128,10 +147,14 @@ public class PsiCapturedWildcardType extends PsiType.Stub {
return PsiWildcardType.createSuper(myContext.getManager(), ((PsiCapturedWildcardType)bound).getUpperBound());
}
else {
return PsiType.getJavaLangObject(myContext.getManager(), getResolveScope());
return myUpperBound != null ? myUpperBound : PsiType.getJavaLangObject(myContext.getManager(), getResolveScope());
}
}
public void setUpperBound(PsiType upperBound) {
myUpperBound = upperBound;
}
@NotNull
public PsiWildcardType getWildcard() {
return myExistential;
@@ -141,4 +164,8 @@ public class PsiCapturedWildcardType extends PsiType.Stub {
public PsiElement getContext() {
return myContext;
}
public PsiTypeParameter getTypeParameter() {
return myParameter;
}
}
@@ -394,7 +394,7 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
}
}
}
} else if (substituted instanceof PsiWildcardType && ((PsiWildcardType)substituted).isSuper()) {
} else if (substituted instanceof PsiWildcardType && ((PsiWildcardType)substituted).isSuper() && !(oldSubstituted instanceof PsiCapturedWildcardType)) {
final PsiType erasure = TypeConversionUtil.erasure(((PsiWildcardType)substituted).getBound());
if (erasure != null) {
final PsiType[] boundTypes = typeParameter.getExtendsListTypes();
@@ -0,0 +1,30 @@
class Test<T > {
interface Event{}
interface EventListener<V extends Event> {
void handleEvent(V event);
}
public void addListener(EventListener<? super T> listener) {
EventListener<? extends Event> localListener = listener;
<error descr="Incompatible types. Found: 'Test.EventListener<capture<? super T>>', required: 'Test.EventListener<? super Test.Event>'">EventListener<? super Event> localListener1 = listener;</error>
}
}
class Test1 {
public static class Entity<E extends Entity<E>> {
public final <T, V extends EntityVisitor<? super E, T>> T handle(final V visitor) {
return visitor.handle(this);
}
}
public interface EntityVisitor<E extends Entity<E>, T> {
T handle(Entity<? extends E> e);
}
}
@@ -9,7 +9,7 @@ abstract class ProcedureService {
abstract <C extends Command<Result>> Class<? extends Procedure<Command<Result>>> getProcedure(Class<C> cmd);
public <C extends Command<Result>> void execute(Class<? extends Command> aClass) {
Class<Procedure<Command<Result>>> procedureClass = getProcedure(aClass);
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? extends Procedure<Command<Result>>>>', required: 'java.lang.Class<Procedure<Command<Result>>>'">Class<Procedure<Command<Result>>> procedureClass = getProcedure(aClass);</error>
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? extends Command>>', required: 'java.lang.Class<Command>'">Class<Command> c = aClass;</error>
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? extends Command>>', required: 'java.lang.Class<C>'">Class<C> c1 = aClass;</error>
}
@@ -20,7 +20,7 @@ class Bug2<T extends Integer>{
}
void bug1(Parametrized<? super T> param) {
<error descr="Inferred type 'capture<? super T>' for type parameter 'I' is not within its bound; should extend 'java.lang.Number'">foo(param)</error>;
foo(param);
}
@@ -35,7 +35,7 @@ class Test {
}
void bug1(Parametrized<? super T> param) {
<error descr="Inferred type 'java.io.Serializable' for type parameter 'I' is not within its bound; should extend 'java.lang.Number'">foo(param)</error>;
<error descr="Inferred type 'capture<? super T>' for type parameter 'I' is not within its bound; should extend 'java.lang.Number'">foo(param)</error>;
}
@@ -372,6 +372,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA126633() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
public void testIDEA124363() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
public void testIDEA78402() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
public void testSuperCaptureSubstitutionWhenTypeParameterHasUpperBounds() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
public void testParameterBoundsWithCapturedWildcard() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
//jdk should propagate LL 1.4 but actually it provides LL 1.7?!
public void testCastObjectToIntJdk14() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_4, false); }
@@ -688,7 +688,7 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
public void testIDEA110869() {
doTest();
}
/*public void testIDEA110947() { doTest5(false); }*/
public void testIDEA110947() { doTest(false); }
public void testIDEA112122() {
doTest();
}