Going beyond a basic Going beyond a basic ownership system in Spec#ownership system in Spec#
K. Rustan M. LeinoK. Rustan M. LeinoMicrosoft Research, Redmond, WAMicrosoft Research, Redmond, WA
Joint work with:Joint work with:
Peter MüllerPeter MüllerAngela WallenburgAngela Wallenburg
ESF workshop on Java program verification, Nijmegen, NL, 18 Oct 2006
Object invariantsObject invariants
0.0. Simple objectsSimple objects**
1.1. Aggregate objectsAggregate objects**
2.2. Immutable typesImmutable types****
3.3. SubclassesSubclasses******
4.4. Additive invariantsAdditive invariants**
*) previous work on Boogie methodology**) L+M+W
***) L+W
0. When do invariants hold?0. When do invariants hold?classclass Car { Car {
intint speed; speed;intint windResistance; windResistance;
invariantinvariant windResistance == K * speed * speed; windResistance == K * speed * speed;
publicpublic Car() { speed = Car() { speed = 0; windResistance = 0; windResistance = 0; }0; }
publicpublic voidvoid SetSpeed( SetSpeed(intint kmph) { kmph) {speed = speed = kmph;kmph;windResistance = windResistance = K * speed * speed;K * speed * speed;
}}
0. When do invariants hold?0. When do invariants hold?classclass Car { Car {
intint speed; speed;intint windResistance; windResistance;
invariantinvariant windResistance == K * speed * speed; windResistance == K * speed * speed;
publicpublic Car() { speed = Car() { speed = 0; windResistance = 0; windResistance = 0; }0; }
publicpublic voidvoid SetSpeed( SetSpeed(intint kmph) { kmph) {speed = speed = kmph;kmph;windResistance = windResistance = K * speed * speed;K * speed * speed;
}}
0. When do invariants hold?0. When do invariants hold?classclass Car { Car {
intint speed; speed;intint windResistance; windResistance;
invariantinvariant windResistance == K * speed * speed; windResistance == K * speed * speed;
publicpublic Car() { speed = Car() { speed = 0; windResistance = 0; windResistance = 0; }0; }
publicpublic voidvoid SetSpeed( SetSpeed(intint kmph) { kmph) {speed = speed = kmph; P(kmph; P( ););windResistance = windResistance = K * speed * speed;K * speed * speed;
}}Invariant
temporarilyviolated
—what if Pcalls back?
Object statesObject states
• MutableMutable– Object invariant might be violatedObject invariant might be violated– Field updates are allowedField updates are allowed
• ValidValid– Object invariant holdsObject invariant holds– Field updates not allowedField updates not allowed
The heap (the object store)The heap (the object store)
The heap (the object store)The heap (the object store)
MutableValid
To mutable and back: To mutable and back: exposeexpose
classclass Car { Car {intint speed; speed;intint windResistance; windResistance;invariantinvariant windResistance == K * speed * speed; windResistance == K * speed * speed;……publicpublic voidvoid SetSpeed( SetSpeed(intint kmph) kmph)
requiresrequires thisthis.valid;.valid;{{
exposeexpose ( (thisthis) {) {speed = speed = kmph;kmph;windResistance = windResistance = K * speed * speed;K * speed * speed;
}}}}
changes thisfrom valid to mutable
changes thisfrom mutable to valid
can update speed,because this.mutable
Summary for simple objects:Summary for simple objects:
((o • o.mutable o • o.mutable Inv(o)) Inv(o))
x.f = E;x.f = E;check x.mutable
invariantinvariant … … thisthis.f …;.f …;
o.mutable ¬ o.valid
Summary for simple objects:Summary for simple objects:
((o • o.mutable o • o.mutable Inv(o)) Inv(o))
exposeexpose (x) { … } (x) { … }x.valid := false x.valid := true
check x.valid check Inv(x)
o.mutable ¬ o.valid
1. Aggregate objects1. Aggregate objectsclassclass Seat { Seat { publicpublic voidvoid Move( Move(intint pos) pos) requiresrequires
thisthis.valid; … }.valid; … }
classclass Car { Car {
Seat s;Seat s;
publicpublic voidvoid Adjust(Profile p) Adjust(Profile p)requiresrequires thisthis.valid .valid p.valid; p.valid;
{{s.Move(p.SeatPosition);s.Move(p.SeatPosition);
}}
OwnershipOwnership
Points to owner
Ownership domainsOwnership domains
Points to owner
Ownership domainsOwnership domains
Points to owner
x
y z
x owns y and z
y and z are componentsin the representation of x
y and z are peers
Points to ownerMutable objectValid object
An object is only as valid as its An object is only as valid as its componentscomponents
Representation (rep) fieldsRepresentation (rep) fieldsclassclass Seat { Seat { publicpublic voidvoid Move( Move(intint pos) pos) requiresrequires thisthis.Consistent; … }.Consistent; … }
classclass Car { Car {
reprep Seat s; Seat s;
publicpublic voidvoid Adjust(Profile p) Adjust(Profile p)requiresrequires thisthis.Consistent .Consistent p.Consistent; p.Consistent;
{{exposeexpose ( (thisthis) {) {
s.Move(p.SeatPosition);s.Move(p.SeatPosition);}}
}}
o.Consistent o.owner.mutable o.valid
Peer fields and peer validityPeer fields and peer validityclassclass Seat { Seat { publicpublic voidvoid Move( Move(intint pos) pos) requiresrequires thisthis.PeerConsistent; … }.PeerConsistent; … }
classclass Car { Car {
reprep Seat s; Seat s; peerpeer Seat s; Seat s;
publicpublic voidvoid Adjust(Profile p) Adjust(Profile p) publicpublic voidvoid Adjust(Position p) Adjust(Position p)requiresrequires thisthis.PeerConsistent .PeerConsistent
requiresrequires thisthis.PeerConsistent .PeerConsistent p.PeerConsistent; p.PeerConsistent; p.PeerConsistent; p.PeerConsistent;
{{ {{exposeexpose ( (thisthis) {) {
s.Move(p.SeatPosition);s.Move(p.SeatPosition); s.Move(p.SeatPosition);s.Move(p.SeatPosition);}}
}} }}o.Consistent o.owner.mutable o.valid
o.PeerConsistent o.owner.mutable (p • p.owner = o.owner p.valid)
Summary for aggregate objects:Summary for aggregate objects:
((o • o.mutable o • o.mutable Inv(o)) Inv(o))
x.f = E;x.f = E;check x.mutable
rep rep TT t;t;invariantinvariant … … thisthis.t.f …;.t.f …;
((o • o.mutable o • o.mutable o.owner.mutable) o.owner.mutable)
x.valid := false
Summary for aggregate objects:Summary for aggregate objects:
exposeexpose (x) { … } (x) { … }x.valid := true
check x.validcheck x.owner.mutable
check (r • r.owner=x r.valid)check Inv(x)
((o • o.mutable o • o.mutable Inv(o)) Inv(o))((o • o.mutable o • o.mutable o.owner.mutable) o.owner.mutable)
2. Immutable types2. Immutable typesclass class String {String {
String SubString(String SubString(intint st, st, intint len) len) requiresrequires thisthis.PeerConsistent;.PeerConsistent;… }… }
classclass Car { Car {
String serialNumber;String serialNumber;
publicpublic String Year() String Year()requiresrequires thisthis.PeerConsistent;.PeerConsistent;
{{returnreturn serialNumber.Substring(12, 4); serialNumber.Substring(12, 4);
}}
Note: cannotuse rep,since Car
cannot expectto be the
sole owner
Points to ownerMutable objectValid objectImmutable object
Ever-peer-consistent (immutable) Ever-peer-consistent (immutable) objectsobjects
Summary for immutable types:Summary for immutable types:((o • Immutable(typeof(o)) o • Immutable(typeof(o))
o.PeerConsistent)o.PeerConsistent)
x.f = E;x.f = E;check x.mutable
[Immutable][Immutable] class class M { TM { T f; f; … }… }
class class C {C {MM m;m;invariantinvariant … … thisthis.m.f …;.m.f …;
x.valid := false
Summary for immutable types:Summary for immutable types:
exposeexpose (x) { … } (x) { … }x.valid := true
check ¬ Immutable(typeof(x))check …
check …
((o • Immutable(typeof(o)) o • Immutable(typeof(o)) o.PeerConsistent)o.PeerConsistent)
Immutable is determined from Immutable is determined from static type (except for static type (except for objectobject))
[Immutable] [Immutable] classclass C C extendsextends B { … B { … }}
• [Immutable] allowed on C if either[Immutable] allowed on C if either– B is [Immutable] orB is [Immutable] or– B is B is objectobject
• [Immutable] required on C if[Immutable] required on C if– B is [Immutable]B is [Immutable]
3. Subclasses3. Subclassesclassclass Car { Car {
intint speed; speed;invariantinvariant 0 ≤ speed; 0 ≤ speed;……
}}
classclass LuxuryCar LuxuryCar extendsextends Car { Car {Radio r;Radio r;invariantinvariant 6 ≤ r.CDCapacity; 6 ≤ r.CDCapacity;……
}}
Owners are pairsOwners are pairs
• To support subclasses with To support subclasses with invariants, we change owners to be invariants, we change owners to be pairs:pairs:
(object reference, class frame)(object reference, class frame)
Invariants and subclassesInvariants and subclasses
class A { … }
class B extends A { … }
Points to owner
Object
A
B
Summary for subclasses:Summary for subclasses:
((o,T • (o,T).mutable o,T • (o,T).mutable Inv InvTT(o))(o))
x.f = E;x.f = E;check (x,C).mutable
class class C C extendsextends B { B { F F f;f; invariantinvariant … … thisthis.f …;.f …;
((o,T • (o,T).mutable o,T • (o,T).mutable o.owner.mutable) o.owner.mutable)
(x,C).valid := false
Summary for subclasses:Summary for subclasses:
CC x; …x; …exposeexpose (x) { … } (x) { … }
(x,C).valid := true
check (x,C).validcheck x.owner.mutable
check (r • r.owner=(x,C) (R • (r,R).valid))check InvC(x)
((o,T • (o,T).mutable o,T • (o,T).mutable Inv InvTT(o))(o))((o,T • (o,T).mutable o,T • (o,T).mutable o.owner.mutable) o.owner.mutable)
4. Additive invariants4. Additive invariantsclassclass Car { Car {
intint speed; speed;……
}}classclass LuxuryCar LuxuryCar extendsextends Car { Car {
Radio r;Radio r;invariantinvariant speed > 60 speed > 60 r.SoundBooster= r.SoundBooster=truetrue;;overridesoverrides voidvoid SetSpeed( SetSpeed(intint kmph) { kmph) {
exposeexpose ( (thisthis) {) {basebase.SetSpeed(kmph);.SetSpeed(kmph);ifif (speed > 60) { … } (speed > 60) { … }
}}}}
}}
An additive frame is only as An additive frame is only as valid as its subclass framesvalid as its subclass frames
class A { … }
class B extends A { … }
Points to ownerMutable objectValid object
Object
A
B
Summary for additive invariants:Summary for additive invariants:
((o,T • (o,T).mutable o,T • (o,T).mutable Inv InvTT(o))(o))
x.f = E;x.f = E;check (U • U <: B (o,U).mutable)
classclass B B extends extends A {A { additive additive F f; F f; … }… }class class C C extendsextends B { B { invariantinvariant … … thisthis.f …;.f …;
((o,T • (o,T).mutable o,T • (o,T).mutable o.owner.mutable) o.owner.mutable)
Summary for additive invariants:Summary for additive invariants:((o,T • (o,T).mutable o,T • (o,T).mutable Inv InvTT(o))(o))((o,T • (o,T).mutable o,T • (o,T).mutable o.owner.mutable) o.owner.mutable)
((o,T • (o,T).transmut o,T • (o,T).transmut (o,T).mutable (o,T).mutable ((U • U <: T U • U <: T (o,U).transmut)) (o,U).transmut))
CC x; …x; …additiveadditive exposeexpose (x) { … } (x) { … }
(x,C).valid := true(x,C).transmut :=
false
check (x,C).valid (U • U <: C (x,U).transmut) check x.owner.mutable
check (r • r.owner=(x,C) (R • (r,R).valid))check InvC(x)
≠
≠
(x,C).valid := false(x,C).transmut :=
true
Object invariants in Spec#Object invariants in Spec#• Spec# syntactically checks that invariants are admissibleSpec# syntactically checks that invariants are admissible• Ownership is specified with the [Owned] attributeOwnership is specified with the [Owned] attribute• We first supported only We first supported only reprep ownership relations ownership relations
– peerpeer relationships are often useful too relationships are often useful too– we now use we now use PeerConsistent PeerConsistent as the default method preconditionas the default method precondition– owners are set automatically on assignments of owners are set automatically on assignments of reprep and and peerpeer fields fields
• An immutable class/interface is specified with [Immutable]An immutable class/interface is specified with [Immutable]• We first supported only additive invariants in Spec#We first supported only additive invariants in Spec#
– non-additive invariants are easier to work withnon-additive invariants are easier to work with– non-additive expose is now the defaultnon-additive expose is now the default– implementation restriction: no further expose allowed on an object implementation restriction: no further expose allowed on an object
while a non-additive expose is in progresswhile a non-additive expose is in progress
• Additive methods (those that update the additive fields Additive methods (those that update the additive fields mentioned in additive invariants) require dynamic dispatch mentioned in additive invariants) require dynamic dispatch and use precondition and use precondition ConsistentConsistent
Summary and conclusionsSummary and conclusions• Rich object structures need Rich object structures need
specification and verification supportspecification and verification support– simple invariantssimple invariants– aggregate objectsaggregate objects– subclassessubclasses– additive invariantsadditive invariants– visibility-based invariantsvisibility-based invariants– observer invariantsobserver invariants– static class invariantsstatic class invariants– ……