Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 489027

Summary: @Inject should imply @Nonnull in annotations based null analysis
Product: [Eclipse Project] JDT Reporter: yac yac <yac>
Component: CoreAssignee: Stephan Herrmann <stephan.herrmann>
Status: CLOSED DUPLICATE QA Contact:
Severity: normal    
Priority: P3 CC: stephan.herrmann
Version: 4.5.1   
Target Milestone: 4.6 M6   
Hardware: PC   
OS: Linux   
Whiteboard:

Description yac yac CLA 2016-03-04 10:01:45 EST
@Inject should imply @Nonnull in annotations based null analysis

class A {
  @Inject Foo foo;

  public doStuff() {
     privateImpl(foo);
  }

  private doImpl(@Nonnull Foo foo) {
    // should not trigger unchecked conversion here.
  }
}
Comment 1 Stephan Herrmann CLA 2016-03-04 10:29:35 EST
Generally this has been implemented, see bug 400421 comment 5

Which @Inject annotation are you using?

Please also correct your example (privateImpl or doImpl?) and tell me where exactly you see a problem.
Comment 2 yac yac CLA 2016-03-07 06:09:17 EST
Corrected example:


import javax.annotation.ParametersAreNonnullByDefault;
import javax.inject.Inject;

@ParametersAreNonnullByDefault
public class A {
  @Inject Foo foo;

  public void doStuff() {
     doImpl(foo); // Null type safety: The expression of type 'Foo' needs unchecked conversion to conform to '@Nonnull Foo'
  }

  private void doImpl(Foo foo) {
  }
}
Comment 3 Stephan Herrmann CLA 2016-03-07 17:56:18 EST
Thanks, I can reproduce if and only if: 
- the project is configured for Java 8
- null annotations are *not* Java 8 TYPE_USE annotations

Note, that for Java 8 source code we generally recommend to use TYPE_USE null annotations. This combination is much more thoroughly tested, than the mix of old annotations and new language level. Additionally, the new annotations allow  much more precise / expressive null contracts.
Comment 4 Stephan Herrmann CLA 2016-03-07 19:03:59 EST
Another observation: the solution in bug 400421 only avoids an error against a field that is marked both @NonNull and @Inject: for this case the lack of a non-null initialization no longer triggers an error. That fix does *not* automatically mark an injected field as @NonNull. 


The root problem in this bug, however, is that the compiler got confused about the mix mentioned in comment 3. In that situation the default nullness annotation didn't fully work as documented [1].

This has been fixed via Bug 488021, and now the field is correctly marked as @NonNull due to the default nullness annotation.

I understand that this isn't exactly what the bug title speaks about (= implicitly marking a field as @NonNull due to @Inject), but I believe that the current solution should be sufficient. I don't think we want to give more implicit meaning to annotations that we don't control and that don't explicitly state any non-null guarantee.

[1] http://help.eclipse.org/kepler/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjdt%2Fannotation%2FNonNullByDefault.html

*** This bug has been marked as a duplicate of bug 488021 ***