blob: 976f40a75366f501f120285e680ce5f6c8176c65 [file] [log] [blame]
// Test case for issue 2432:
// https://github.com/typetools/checker-framework/issues/2432
import java.util.List;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.PolyNull;
public class Issue2432 {
void jdkAnnotation(List<@PolyNull Object> nl, @Nullable Object no, @PolyNull Object po) {
// :: error: (argument)
nl.add(null);
// :: error: (argument)
nl.add(no);
// OK
nl.add(po);
}
// receiver's poly annotations in declaration are different from the ones in invocation
void polyReceiverType(
TypeArgClass<@PolyNull Object> tc,
@NonNull Object nno,
@Nullable Object no,
@PolyNull Object po) {
// :: error: (argument)
Object object = tc.echo(no);
// :: error: (assignment)
nno = tc.echo(po);
// No error. Return value remains @PolyNull.
// Note po's @PolyNull is unsubstitutable (from parameter but not from declaration)
po = tc.echo(po);
}
// the following two methods tests pesudo assignment of arguments with poly annotation
void polyAssignment(TypeArgClass<@NonNull Object> nnc, @PolyNull Object po) {
// :: error: (argument)
nnc.echo(po);
}
void polyAssignment2(TypeArgClass<@Nullable Object> nc, @PolyNull Object po) {
// No error
nc.echo(po);
// :: error: (assignment)
po = nc.echo(po);
}
// a "foo function" with 2 poly annotations, where one of them appears in type argument
// purpose: test invocation without using explicit receiver
@PolyNull Object foo2PolyTypeArg(
TypeArgClass<@PolyNull Object> pc, @PolyNull Object po, @NonNull Object nno) {
return pc.add(nno, po);
}
// lub tests without receiver
// lub combination: (@Nullable, @Nullable) = @Nullable
void lubWithTypeArgNoReceiver1(TypeArgClass<@Nullable Object> nc, @Nullable Object no) {
@NonNull Object nno = new Object();
// No error
foo2PolyTypeArg(nc, no, nno);
}
// lub combination: (@NonNull, @NonNull) = @NonNull
void lubWithTypeArgNoReceiver2(TypeArgClass<@NonNull Object> nnc, @NonNull Object nno) {
// No error
foo2PolyTypeArg(nnc, nno, nno);
}
// lub combination: (@Nullable, @NonNull) = @Nullable
void lubWithTypeArgNoReceiver3(TypeArgClass<@Nullable Object> nc, @NonNull Object nno) {
// No error
foo2PolyTypeArg(nc, nno, nno);
}
// lub combination: (@NonNull, @Nullable) = @Nullable
void lubWithTypeArgNoReceiver4(TypeArgClass<@NonNull Object> nnc, @Nullable Object no) {
// :: error: (argument)
foo2PolyTypeArg(nnc, no, new Object());
}
// lub test with receiver
// T dummy in tripleAdd is to ensure poly annotations from declaration is handled separately
void lubWithReceiver(
TypeArgClass<@PolyNull Object> pc, @Nullable Object no, @NonNull Object nno) {
// :: error: (argument)
pc.tripleAdd(no, nno, no);
// No error
pc.tripleAdd(no, nno, nno);
}
// ensure poly annotations from declaration is handled separately from poly from other context
void declarationPolyInParameter(
TypeArgClass<@PolyNull Object> pc, @Nullable Object no, @NonNull Object nno) {
// No error
pc.echo(nno, no);
// the invocation is valid, while the assignment is not
// :: error: (assignment)
@NonNull Object nonnull = pc.echo(nno, no);
}
private class TypeArgClass<T> {
@PolyNull Object add(@PolyNull Object obj, T dummy) {
return obj;
}
@PolyNull Object tripleAdd(@PolyNull Object o1, @PolyNull Object o2, T dummy) {
return o1;
}
T echo(T obj) {
return obj;
}
T echo(T obj, @PolyNull Object dummy) {
return obj;
}
}
}