import checkers.igj.quals.*;
/**
* An Immutable class that represent a date
*/
@Immutable
class Date {
int time; // epoch time
public Date(int time) @AssignsFields {
this.time = time;
}
public int getYear() { return 0; }
public int getMonth() { return 0; }
public int getDay() { return 0; }
public int testMutate() {
this.time = 4; // Error: Cannot re-assign in a method with RO receiver
this.time++; // Error: Cannot re-assign in a method with RO receiver
}
public int mutableReciever() /*@Mutable*/ // Error: No method with mutable receiver within Immutable Class
{ }
}
@I
class Point {
double x;
double y;
Point(double x, double y) @AssignsFields {
setX(x);
setY(y);
}
void setX(double x) @AssignsFields { this.x = x; }
void setY(double y) @AssignsFields { this.y = y; }
double getX() /*@ReadOnly*/ { return x; }
double getY() /*@ReadOnly*/ { return y; }
public int hashCode() /*@ReadOnly*/ {
x += 4; // Error: ReadOnly receiver
}
public static @I Point getMidPoint(@I Point p1, @I Point p2) {
return new @I Point((p1.getX() + p2.getX()) / 2.0,
(p1.getY() + p2.getY()) / 2.0);
}
public static void test() {
@Immutable Point p1 = new /*@Immutable*/ Point(1,1);
@Immutable Point p2 = new /*@Mutable*/ Point (1, 1); // Error: Incompatible types
@Mutable Point p3 = new /*@Mutable*/ Point(1,1);
@ReadOnly Point p4 = new /*@Mutable*/ Point(1, 1);
p1.setX(4); // Error: Cannot mutate an immutable object
p4.setX(4); // Error: Cannot mutate through a readOnly reference
@Immutable Point mp1 = getMidPoint(p1, p1); // return value resolves to Immutable
@Immutable Point mp2 = getMidPoint(p3, p3); // Error: return value resolves to Mutable
@Mutable Point mp3 = getMidPoint(p3, p3); // resolves to Mutable
@Immutable Point mp4 = getMidPoint(p4, p4); // Error: return value resolves to Immutable
}
}
@I
class TestClass {
void mutableReceiver() /*@Mutable*/ { }
void readOnlyReceiver() /*@ReadOnly*/ { }
void immutableReceiver() /*@Immutable*/ { }
static void isMutable(@Mutable TestClass tc) { }
static void isImmutable(@Immutable TestClass tc) { }
static void isRO(@ReadOnly TestClass tc) { }
TestClass() @AssignsFields {
readOnlyReceiver();
mutableReceiver(); // Error: cannot call method with mutable receiver
immutableReceiver(); // Error: Cannot call method with immutable receiver
}
void testMethod1() /*@ReadOnly*/ {
readOnlyReceiver();
mutableReceiver(); // Error: cannot call method with mutable receiver within method with ReadOnly receiver
isRO(this);
isMutable(this); // Error: this escapes as RO
}
void testMethod2() /*@Mutable*/ {
immutableReceiver(); // Error: cannot call method with immutable receiver
isRO(this);
isMutable(this); // this escapes as mutable
isImmutable(this); // Error: this escapes as Immutable
}
void testMethod3() /*@Immutable*/ {
immutableReceiver();
isRO(this);
isMutable(this); // Error: this escapes as immutable
isImmutable(this); // this escapes as mutable
}
}