public class Container { private /*@ spec_public @*/ int a; /*@ private normal_behavior @ assignable \nothing; @ ensures true; @*/ private /*@ helper @*/ Container() {} /*@ public normal_behavior @ assignable \nothing; @ ensures \result.a == 127; @*/ public static /*@ pure @*/ Container allocate() { Container c = new Container(); c.a = 127; return c; } /*@ public normal_behavior @ assignable \nothing; @ ensures \result <==> (obj instanceof Container) && ((Container) obj).a == a; @*/ public /*@ pure @*/ boolean equals(Object obj) { return (obj instanceof Container) && ((Container) obj).a == a; } public static class ContainerUser { private /*@ spec_public non_null @*/ Container c; /*@ private normal_behavior @ assignable c; @ ensures true; @*/ private /*@ helper @*/ ContainerUser() { c = new Container(); } /*@ public normal_behavior @ assignable \nothing; @ //ensures Container.allocate() instanceof Container; @ ensures \result.c.equals(Container.allocate()); @ // edit: turning this around into "Container.allocate().equals(\result.c)" does @ // establish that \result.c is an instance of Container, but the type system and @ // fact that \result.c != null should already establish this @*/ public static ContainerUser allocate() { ContainerUser user = new ContainerUser(); user.c = Container.allocate(); return user; } public void test() { ContainerUser user = allocate(); Container cont = Container.allocate(); //@ assert user instanceof ContainerUser; // passes //@ assert cont instanceof Container; // passes //@ assert user.c.a == 127; // passes //@ assert user.c instanceof Container; // fails - fixed } } } // The original buggy example surfaced two problems: // 1) assignment to user.c was not allowed, even though user was a fresh object // 2) user.c could not be shown to have type Container, even though it is declared to be that type