import org.checkerframework.common.aliasing.qual.*; class TypeRefinement { /** * Type refinement is treated in the usual way, except that at (pseudo-)assignments the RHS may * lose its type refinement, before the LHS is type-refined. * * <p>The RHS always loses its type refinement (it is widened to @MaybeAliased, and its declared * type must have been @MaybeAliased) except in the following cases: * * <ol> * <li>The RHS is a fresh expression. * <li>The LHS is a @NonLeaked formal parameter and the RHS is an argument in a method call or * constructor invocation. * <li>The LHS is a @LeakedToResult formal parameter, the RHS is an argument in a method call * or constructor invocation, and the method's return value is discarded. * <ol> */ // Test cases for the Aliasing type refinement cases below. // One method for each exception case. The usual case is tested in every method too. // As annotated in stubfile.astub, String() has type @Unique @NonLeaked. void rule1() { String unique = new String(); // unique is refined to @Unique here, according to the definition. isUnique(unique); String notUnique = unique; // unique loses its refinement. //:: error: (argument.type.incompatible) isUnique(unique); //:: error: (argument.type.incompatible) isUnique(notUnique); } void rule2() { String unique = new String(); isUnique(unique); nonLeaked(unique); isUnique(unique); leaked(unique); //:: error: (argument.type.incompatible) isUnique(unique); } void rule3() { String unique = new String(); isUnique(unique); leakedToResult(unique); isUnique(unique); String notUnique = leakedToResult(unique); //:: error: (argument.type.incompatible) isUnique(unique); } void nonLeaked(@NonLeaked String s) {} void leaked(String s) {} String leakedToResult(@LeakedToResult String s) { return s; } // @NonLeaked so it doesn't refine the type of the argument. void isUnique(@NonLeaked @Unique String s) {} }