import checkers.igj.quals.*; @I public class Fields { @Assignable @I Fields left; @I Fields next; @ReadOnly Fields ro; Fields() @AssignsFields { } Fields(int arg) @AssignsFields { left = new @I Fields(); next = new @Mutable Fields(); // should emit error next = new @Immutable Fields(); // should emit error ro = this; } // Methods for testing static void isRO(@ReadOnly Fields f) { } static void isMutable(@Mutable Fields f) { } static void isImmutable(@Immutable Fields f) { } @I Fields getLeft() @ReadOnly { return left; } @I Fields getNext() @ReadOnly { return next; } @ReadOnly Fields getRO() @ReadOnly { return ro; } void mutableReciever() @Mutable { // all but ro should be mutable isRO(left); isRO(next); isRO(ro); // TestLeft isMutable(left); isMutable(this.left); isMutable(getLeft()); isImmutable(left); // should emit error isImmutable(this.left); // should emit error isImmutable(getLeft()); // should emit error // Test Right isMutable(next); isMutable(this.next); isMutable(getNext()); isImmutable(next); // should emit error isImmutable(this.next); // should emit error isImmutable(getNext()); // should emit error // Test RO isMutable(ro); // should emit error isMutable(this.ro); // should emit error isMutable(getRO()); // should emit error isImmutable(ro); // should emit error isImmutable(this.ro); // should emit error isImmutable(getRO()); // should emit error } void immutableReceiver() @Immutable { // all but ro should be mutable isRO(left); isRO(next); isRO(ro); // TestLeft isMutable(left); // should emit error isMutable(this.left); // should emit error isMutable(getLeft()); // should emit error isImmutable(left); isImmutable(this.left); isImmutable(getLeft()); // Test Right isMutable(next); // should emit error isMutable(this.next); // should emit error isMutable(getNext()); // should emit error isImmutable(next); isImmutable(this.next); isImmutable(getNext()); // Test RO isMutable(ro); // should emit error isMutable(this.ro); // should emit error isMutable(getRO()); // should emit error isImmutable(ro); // should emit error isImmutable(this.ro); // should emit error isImmutable(getRO()); // should emit error } void roMethod() @ReadOnly { // all but ro should be mutable isRO(left); isRO(next); isRO(ro); // TestLeft isMutable(left); // should emit error isMutable(this.left); // should emit error isMutable(getLeft()); // should emit error isImmutable(left); // should emit error isImmutable(this.left); // should emit error isImmutable(getLeft()); // should emit error // Test Right isMutable(next); // should emit error isMutable(this.next); // should emit error isMutable(getNext()); // should emit error isImmutable(next); // should emit error isImmutable(this.next); // should emit error isImmutable(getNext()); // should emit error // Test RO isMutable(ro); // should emit error isMutable(this.ro); // should emit error isMutable(getRO()); // should emit error isImmutable(ro); // should emit error isImmutable(this.ro); // should emit error isImmutable(getRO()); // should emit error } void assignsFieldsMethod() @AssignsFields { // all but ro should be mutable isRO(left); isRO(next); isRO(ro); // TestLeft isMutable(left); // should emit error isMutable(this.left); // should emit error isMutable(getLeft()); // should emit error isImmutable(left); // should emit error isImmutable(this.left); // should emit error isImmutable(getLeft()); // should emit error // Test Right isMutable(next); // should emit error isMutable(this.next); // should emit error isMutable(getNext()); // should emit error isImmutable(next); // should emit error isImmutable(this.next); // should emit error isImmutable(getNext()); // should emit error // Test RO isMutable(ro); // should emit error isMutable(this.ro); // should emit error isMutable(getRO()); // should emit error isImmutable(ro); // should emit error isImmutable(this.ro); // should emit error isImmutable(getRO()); // should emit error } static void testNewMutableClass() { // all but ro should be mutable isRO(new @Mutable Fields().left); isRO(new @Mutable Fields().next); isRO(new @Mutable Fields().ro); // TestLeft isMutable(new @Mutable Fields().left); isMutable(new @Mutable Fields().getLeft()); isImmutable(new @Mutable Fields().left); // should emit error isImmutable(new @Mutable Fields().getLeft()); // should emit error // Test Right isMutable(new @Mutable Fields().next); isMutable(new @Mutable Fields().getNext()); isImmutable(new @Mutable Fields().next); // should emit error isImmutable(new @Mutable Fields().getNext()); // should emit error // Test RO isMutable(new @Mutable Fields().ro); // should emit error isMutable(new @Mutable Fields().getRO()); // should emit error isImmutable(new @Mutable Fields().ro); // should emit error isImmutable(new @Mutable Fields().getRO()); // should emit error } static void testNewImmutableClass() { // all but ro should be mutable isRO(new @Immutable Fields().left); isRO(new @Immutable Fields().next); isRO(new @Immutable Fields().ro); // TestLeft isMutable(new @Immutable Fields().left); // should emit error isMutable(new @Immutable Fields().getLeft()); // should emit error isImmutable(new @Immutable Fields().left); isImmutable(new @Immutable Fields().getLeft()); // Test Right isMutable(new @Immutable Fields().next); // should emit error isMutable(new @Immutable Fields().getNext()); // should emit error isImmutable(new @Immutable Fields().next); isImmutable(new @Immutable Fields().getNext()); // Test RO isMutable(new @Immutable Fields().ro); // should emit error isMutable(new @Immutable Fields().getRO()); // should emit error isImmutable(new @Immutable Fields().ro); // should emit error isImmutable(new @Immutable Fields().getRO()); // should emit error } static void testConditionalMutable() { @Mutable Fields mutable = null; // all but ro should be mutable isRO((true ? mutable : new @Mutable Fields()).left); isRO((true ? mutable : new @Mutable Fields()).next); isRO((true ? mutable : new @Mutable Fields()).ro); // TestLeft isMutable((true ? mutable : new @Mutable Fields()).left); isMutable((true ? mutable : new @Mutable Fields()).getLeft()); isImmutable((true ? mutable : new @Mutable Fields()).left); // should emit error isImmutable((true ? mutable : new @Mutable Fields()).getLeft()); // should emit error // Test Right isMutable((true ? mutable : new @Mutable Fields()).next); isMutable((true ? mutable : new @Mutable Fields()).getNext()); isImmutable((true ? mutable : new @Mutable Fields()).next); // should emit error isImmutable((true ? mutable : new @Mutable Fields()).getNext()); // should emit error // Test RO isMutable((true ? mutable : new @Mutable Fields()).ro); // should emit error isMutable((true ? mutable : new @Mutable Fields()).getRO()); // should emit error isImmutable((true ? mutable : new @Mutable Fields()).ro); // should emit error isImmutable((true ? mutable : new @Mutable Fields()).getRO()); // should emit error } static void testImmutableConditional() { @Immutable Fields immutable = null; // all but ro should be mutable isRO((true ? immutable : new @Immutable Fields()).left); isRO((true ? immutable : new @Immutable Fields()).next); isRO((true ? immutable : new @Immutable Fields()).ro); // TestLeft isMutable((true ? immutable : new @Immutable Fields()).left); // should emit error isMutable((true ? immutable : new @Immutable Fields()).getLeft()); // should emit error isImmutable((true ? immutable : new @Immutable Fields()).left); isImmutable((true ? immutable : new @Immutable Fields()).getLeft()); // Test Right isMutable((true ? immutable : new @Immutable Fields()).next); // should emit error isMutable((true ? immutable : new @Immutable Fields()).getNext()); // should emit error isImmutable((true ? immutable : new @Immutable Fields()).next); isImmutable((true ? immutable : new @Immutable Fields()).getNext()); // Test RO isMutable((true ? immutable : new @Immutable Fields()).ro); // should emit error isMutable((true ? immutable : new @Immutable Fields()).getRO()); // should emit error isImmutable((true ? immutable : new @Immutable Fields()).ro); // should emit error isImmutable((true ? immutable : new @Immutable Fields()).getRO()); // should emit error } }