[Generics] Switching the order of extended interfaces alters the result of @NonNull annotation analysis#5070
Conversation
of @nonnull annotation analysis + report unchecked warning for unannotated 'this' argument + recover the actual contract that introduces an unmet constraint Partly fixes eclipse-jdt#4297
|
This PR fixes some but not all problems observed in #4297 Let's classify use cases: The common situation consists of two independent interfaces that declare methods which are equivalent in terms of JLS, but have different annotations (which JLS doesn't care about). The following considerations hold if those annotations are null annotations evaluated by ecj; 3rd party annotations are out off scope here:
We need to further distinguish the position of the ambiguous annotation: This variant produces a warning already in 4.39: import org.eclipse.jdt.annotation.*;
public class GenericsOrder {
public <T extends b & a> void test(@NonNull T my) {
my.method(null);
}
public <T extends I> void test(@NonNull T my) {
my.method(null); // The call goes through here
}
public static void main(String[] args) {
new GenericsOrder().test(GenericsOrder::mImpl); // problem against regular param 's'
}
public static int mImpl(@NonNull String s) { return 0; }
}
interface a { int method(@NonNull String a); }
interface b { int method(String a); }
interface I extends b, a { }ecj complains: This part is independent of interface order. ✔️ There still is order dependence inside both The original witness from #4297 (comment), however, adds one more trick to the mix: here we are passing a reference to an instance method, where the first parameter of the function type will be implicitly mapped to a This is the main fix in this PR: warn when an unannotated parameter is mapped to the receiver of a reference to an instance method. That witness will now raise Swapping interface order will still change warnings against the bodies of As a side issue, the PR also fixes the exact message in this warning (and its sibling error in case of With this I believe the issue is resolved for method reference as argument to an inconsistent functional interface. 👍 When using the lambda form of the same example, ecj has no extra knowledge about a |
|
I was about to propose this fix for RC1, but at a closer look we are fixing an extreme corner case, depending on all of these conditions:
In this very specific case a relevant problem is not reported, thus hiding the fact that no conflict-free implementation of that functional interface is possible. The bigger problem is that JLS is silent about all this, and thus for 3rd party annotations, for which ecj has no insider knowledge, order dependence cannot be avoided without a fix in JLS. In that light I guess this fix can wait till after 4.40 GA. |
Partly fixes #4297