Community
Participate
Working Groups
Using 4.6-I20151124-1000 I am seeing errors when passing @NonNull to unconstrained parameter. The parameter is generic, so that might have something to do with it. Here is the snippet: void example1() { @Nullable List<String> container = new ArrayList<>(); @NonNull List<String> list = checkNotNull(container); } void example2() { @NonNull List<String> container= new ArrayList<>(); @NonNull List<String> list = checkNotNull(container); // Null constraint mismatch: The type '@NonNull List<String>' is not a valid substitute for the type parameter 'C extends Iterable<T>' } @NonNull <T, C extends Iterable<T>> C checkNotNull(C container) { if (container == null) { throw new NullPointerException(); } return container; } Here is my understanding of this: In the checkNotNull method signature, the C in the parameter and T are unconstrained. Only the C returned is constrained. In example1, the List is @Nullable and the <String> is unconstrained, which is compatible with the unconstrained C and T in checkNotNull. In example2, the List is @NonNull and the <String> is unconstrained, which (I thought!) should be compatible with the unconstrained C and T in checkNotNull. But this gives an error. If I change checkNotNull's parameter to @Nullable C container, example2 works but not example1.
Created attachment 258301 [details] Example project
Created attachment 258302 [details] Example project
Thanks, I can reproduce. It seems the error is only flagged when the invocation to checkNonNull is redundant. Strange.
The bug is in null-aware type inference: We have these TypeBounds: T#0 = java.lang.String @NonNull C#1 <: java.util.List<java.lang.String> from which we derive this constraint: ⟨@NonNull C#1 <: java.util.List<java.lang.String>⟩ seeing the @NonNull we wrongly add it to the nullHints of both input TypeBounds. This can be fixed by performing this transfer (needed for Bug 428985) only when combination of TypeBounds is based on a direct substitution of equal LHS ivars (like T#0 <: Foo & T#0 >: Goo => Goo <: Foo). Additionally, the derivation of the above constraint can be avoided altogether; We are applying this rule: α = U and S <: T imply ⟨S[α:=U] <: T[α:=U]⟩ If neither substitution in the consequent has any effect, then the resulting new constraint is always equivalent to the second input bound, so let's just avoid creating and incorporating it (again).
New Gerrit change created: https://git.eclipse.org/r/61498
Gerrit change https://git.eclipse.org/r/61498 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=a8001f94dedfcf0ea807d46ff48ed3d0c7a3c2ef
Verified for Eclipse Neon Version: Neon 4.6M4 Build id: I20151207-0800