import org.checkerframework.checker.nullness.qual.*; class Test { class Test1<CONTENT extends @Nullable Object> { CONTENT a; // To prevent the warning about un-initialized fields. Test1(CONTENT p1) { a = p1; } public CONTENT get() { return a; } @org.checkerframework.dataflow.qual.Pure public CONTENT get2() { return a; } } class Test2<CONTENT extends @Nullable Object> { @NonNull CONTENT a; // To prevent the warning about un-initialized fields. Test2(@NonNull CONTENT p1) { a = p1; } public @NonNull CONTENT get() { return a; } @org.checkerframework.dataflow.qual.Pure public @NonNull CONTENT get2() { return a; } } /* class Test3<CONTENT extend @Nullable Object> { // Change @Pure to be allowed on fields, or add some other anno. @Pure CONTENT f; // Strangely this assignment succeeded Test3(CONTENT p1) { f = p1; } // But this assignment failed, because the @Pure caused the // other annotations to be erased. public void get3(CONTENT p) { f = p; } } */ class Test4<CONTENT extends @Nullable Object> { private MyPair<CONTENT, CONTENT> userObject; Test4(MyPair<CONTENT, CONTENT> p) { userObject = p; } @org.checkerframework.dataflow.qual.Pure public CONTENT getUserLeft() { return userObject.a; } public class MyPair<T1 extends @Nullable Object, T2 extends @Nullable Object> { public T1 a; public T2 b; public MyPair(T1 a, T2 b) { this.a = a; this.b = b; } } } }