import org.checkerframework.framework.qual.DefaultQualifier;
import org.checkerframework.framework.qual.DefaultQualifiers;
import org.checkerframework.framework.qual.TypeUseLocation;
import polyall.quals.*;
// Test defaulting behavior, e.g. that local variables, casts, and instanceof
// propagate the type of the respective sub-expression and that upper bounds
// are separately annotated.
class Defaulting {
@DefaultQualifier(
value = H1S1.class,
locations = {TypeUseLocation.LOCAL_VARIABLE}
)
class TestLocal {
void m(@H1S1 Object p1, @H1S2 Object p2) {
Object l1 = p1;
//:: error: (assignment.type.incompatible)
Object l2 = p2;
}
}
@DefaultQualifiers({
@DefaultQualifier(
value = H1Top.class,
locations = {TypeUseLocation.LOCAL_VARIABLE}
),
@DefaultQualifier(
value = H1S1.class,
locations = {TypeUseLocation.UPPER_BOUND}
),
@DefaultQualifier(
value = H1S2.class,
locations = {TypeUseLocation.OTHERWISE}
)
})
// Type of x is <@H1S2 X extends @H1S1 Object>, these annotations are siblings
// and should not be in the same bound
//:: error: (bound.type.incompatible)
class TestUpperBound<X extends Object> {
void m(X p) {
@H1S1 Object l1 = p;
//:: error: (assignment.type.incompatible)
@H1S2 Object l2 = p;
Object l3 = p;
}
}
@DefaultQualifiers({
@DefaultQualifier(
value = H1Top.class,
locations = {TypeUseLocation.LOCAL_VARIABLE}
),
@DefaultQualifier(
value = H1S1.class,
locations = {TypeUseLocation.PARAMETER}
),
@DefaultQualifier(
value = H1S2.class,
locations = {TypeUseLocation.OTHERWISE}
)
})
class TestParameter {
void m(Object p) {
@H1S1 Object l1 = p;
//:: error: (assignment.type.incompatible)
@H1S2 Object l2 = p;
Object l3 = p;
}
void call() {
m(new @H1S1 Object());
//:: error: (argument.type.incompatible)
m(new @H1S2 Object());
//:: error: (argument.type.incompatible)
m(new Object());
}
}
@DefaultQualifiers({
@DefaultQualifier(
value = H1Top.class,
locations = {TypeUseLocation.LOCAL_VARIABLE}
),
@DefaultQualifier(
value = H1S1.class,
locations = {TypeUseLocation.PARAMETER}
),
@DefaultQualifier(
value = H1S2.class,
locations = {TypeUseLocation.OTHERWISE}
)
})
class TestConstructorParameter {
TestConstructorParameter(Object p) {
@H1S1 Object l1 = p;
//:: error: (assignment.type.incompatible)
@H1S2 Object l2 = p;
Object l3 = p;
}
void call() {
new TestConstructorParameter(new @H1S1 Object());
//:: error: (argument.type.incompatible)
new TestConstructorParameter(new @H1S2 Object());
//:: error: (argument.type.incompatible)
new TestConstructorParameter(new Object());
}
}
@DefaultQualifiers({
@DefaultQualifier(
value = H1Top.class,
locations = {TypeUseLocation.LOCAL_VARIABLE}
),
@DefaultQualifier(
value = H1S1.class,
locations = {TypeUseLocation.RETURN}
),
@DefaultQualifier(
value = H1S2.class,
locations = {TypeUseLocation.OTHERWISE}
)
})
class TestReturns {
Object res() {
return new @H1S1 Object();
}
void m() {
@H1S1 Object l1 = res();
//:: error: (assignment.type.incompatible)
@H1S2 Object l2 = res();
Object l3 = res();
}
Object res2() {
//:: error: (return.type.incompatible)
return new @H1S2 Object();
}
Object res3() {
//:: error: (return.type.incompatible)
return new Object();
}
}
@DefaultQualifiers({
@DefaultQualifier(
value = H1Top.class,
locations = {TypeUseLocation.LOCAL_VARIABLE}
),
@DefaultQualifier(
value = H1S1.class,
locations = {TypeUseLocation.RECEIVER}
)
})
public class ReceiverDefaulting {
public ReceiverDefaulting() {};
public void m() {}
}
@DefaultQualifiers({
@DefaultQualifier(
value = H1Top.class,
locations = {TypeUseLocation.LOCAL_VARIABLE}
),
})
class TestReceiver {
void call() {
@H1S1 ReceiverDefaulting r2 = new @H1S1 ReceiverDefaulting();
@H1S2 ReceiverDefaulting r3 = new @H1S2 ReceiverDefaulting();
ReceiverDefaulting r = new ReceiverDefaulting();
r2.m();
//:: error: (method.invocation.invalid)
r3.m();
//:: error: (method.invocation.invalid)
r.m();
}
}
}