| Summary: | [null] How-to use null type annotations with generic methods from interfaces in some library you only have as binary JAR? | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Michael Vorburger <mike> |
| Component: | Core | Assignee: | Stephan Herrmann <stephan.herrmann> |
| Status: | VERIFIED DUPLICATE | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | manoj.palat, stephan.herrmann |
| Version: | 4.4 | ||
| Target Milestone: | 4.5 M1 | ||
| Hardware: | PC | ||
| OS: | Linux | ||
| Whiteboard: | |||
From a quick glance I see a chance that bug 438458 can help, hence marking as a bug dependency After playing with this all I can say is: your analysis is correct, this is a problem specific to generic methods that return a value of the parameter type.
By declaring
<T> T foo(T arg);
this API promises: for whatever type you choose for T, foo will return a value of that type. T is not constrained in any way, so this includes the option to choose a @NonNull type for T.
Clients may expect things like this to work:
void test(ITest i) {
@NonNull String s = i.foo("OK");
}
Any implementation that returns null is not compatible to that contract.
In the case of a generic interface, the implementor can modify the contract by constraining the type parameter. Such a means does not exist for generic methods.
Sorry to say: all we can do is to address bug 331651, so you can mark in ITest that null return is legal. Otherwise the contract must be fulfilled by avoiding null returns.
BTW: I'd like to encourage you to reverse your thinking about null: in Java null is always legal and we are trying to restrict this by whatever means. Going forward I believe you're better off by considering null as generally illegal - UNLESS you have specific license by way of an explicit @Nullable annotation. In that light not being allowed to return null is the rule, not a bug.
Still one tiny change that I'm planning to make: ensure that @SuppressWarnings("null") can be used to suppress this problem. You'd need to either:
- enable "[x] Suppress optional errors with '@SuppressWarnings'", or
- downgrade "Violation of null specification" to warning (not recommended)
In either case, use with caution! :)
As of http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=61133b8c5e6da454f7cea747a5c83744e4b067c9 the problem in this bug can now be suppressed using @SuppressWarnings("null"). That's all we can do here. Changing bug dependency to duplication, because no additional change was made for this bug. *** This bug has been marked as a duplicate of bug 438467 *** Verified duplicate in Eclipse Mars 4.5 M1 Build id: I20140804-2000 |
// Imagine this is in some library you only have as binary JAR (cannot modify src) interface ITest { <T> T foo(T arg); // or arg Class<T> or TypeToken<T> + return TypeAdapter<T>, etc. } // This however is your code (src), in a project with null type annotations class Test implements ITest { @Override public <T> T foo(T arg) { return null; } } leads to "Null type mismatch (type annotations): 'null' is not compatible to the free type variable 'T'". In this case you cannot use @Nullable in Test's foo(), because that would lead to "The method @Nullable T foo(T) from Test cannot implement the corresponding method from ITest due to incompatible nullness constraints"... assuming one cannot change ITest, how do you solve this? I have read http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-using_null_type_annotations.htm and (roughly..) understand what's going on here technically. The point of the issue is to raise that, unless there is a trick that I'm missing, it's effectively not (yet, pending bug 331651 ?) possible to enable use of null type annotations in projects with code that overrides generic methods from interfaces in some library you only have as binary JAR? If my understanding is correct, this problem is particular to generic methods, because in the following slightly different example, note that here the interface not the method is generic-ified, you're OK: // This is in some library you only have as binary JAR public interface ITest2<T> { /* NOT <T> */ T foo(T arg); // or arg Class<T> or TypeToken<T> + return TypeAdapter<T>, etc. } // This works - no worries: public class Test2<@Nullable T> implements ITest2<T> { @Override public T foo(T arg) { return null; } }