Stackability, visually 2 3 2 1 1 3 4 4 5 6 time 5 6 stacked non-stacked
Scopability, formally Definition (Scoping) σ ′ � L ′ � l = ( σ, L ) ⋖ ( σ ′ , L ′ ) � ∀ l ∈ dom ( σ ) . ⇒ σ � L � l Theorem (Scopability) � e � ( σ, ρ, ψ ) = ( l , σ ′ ) = ⇒ ( σ, codom ( ρ ) ∪ { ψ } ) ⋖ ( σ ′ , { l } ) 25 / 63
Scopability, visually 3 3 1 9 1 ˟ 4 4 ⟦ e ⟧ (σ, ø, 2) 2 2 7 7 8 5 5 6 6 Heap σ Heap σ ’ the result value 26 / 63
Scopability, visually 3 3 1 9 1 ˟ 4 4 ⟦ e ⟧ (σ, ø, 2) 2 2 7 7 8 5 5 6 6 Heap σ Heap σ ’ the result value σ ′ � 8 � 7 σ � 2 � 7 7 ∈ dom ( σ ) ( σ, 2) ⋖ ( σ ′ , 8) 26 / 63
Local reasoning theorem σ � { ψ } ∪ codom ( ρ ) : hot � e � ( σ, ρ, ψ ) = ( l , σ ′ ) σ ′ � l : hot 27 / 63
Challenges Reasoning Problem Evaluation Inference Model
The basic model cold | warm | hot µ ::= T ::= C µ hot ⊑ warm ⊑ cold 28 / 63
Typestate polymorphism g can be called for any initialization state of this class C { 1 // ... 2 def g(): Int = 100 3 } 4 29 / 63
Typestate polymorphism g can be called for any initialization state of this class C { 1 // ... 2 def g(): Int = 100 3 } 4 • how to express the polymorphism in the system? • how to avoid syntactic overhead for polymorphism? 29 / 63
Flow-sensitivity and typestate polymorphism In a flow-sensitive system, we need to resort to parametric polymorphic because a method has to represent the typestates of this both before and after the method call. class C { 1 ∀ M . M � M def g(): Int = 100 // g: 2 } 3 Qi, Xin and Andrew C. Myers. “Masked types for sound object initialization.” POPL ’09 30 / 63
Flow-insensitivity and typestate polymorphism In a flow-insensitive system, we may resort to subtyping polymorphism to support typestate polymorphism . class C { 1 @cold def g(): Int = 100 2 } 3 Summers, Alexander J. and Peter M¨ uller. “Freedom before commitment.” OOPSLA ’11 31 / 63
Strong monotonicity Hot/warm objects continue to be hot/warm: ⇒ σ ′ � l : µ σ � σ ′ � ∀ l ∈ dom ( σ ) . σ � l : µ = F¨ ahndrich, Manuel and K. Rustan M. Leino. “Heap Monotonic Typestate.” (2003). 32 / 63
Perfect monotonicity Hot/warm fields continue to be hot/warm: σ � σ ′ � ∀ l ∈ dom ( σ ) . ( C , ω ) = σ ( l ) = ⇒ � ( C , ω ′ ) = σ ′ ( l ) ⇒ σ ′ � ω ′ ( f ) : µ ∀ f ∈ dom ( ω ) .σ � ω ( f ) : µ = 33 / 63
Typing rules - T-New Γ; T ⊢ e i : C µ i T i = constrType ( C ) i C µ i < : T i µ = ( ⊔ µ i ) ⊓ warm i ( T-New ) Γ; T ⊢ new C ( e ) : C µ local reasoning and stackability 34 / 63
Typing rules - T-Invoke typestate polymorphism Γ; T ⊢ e : C µ 0 ( µ m , T i , D µ r ) = methodType ( C , m ) µ 0 ⊑ µ m Γ; T ⊢ e i : D µ i D µ i < : T i i i µ = ( ⊔ µ i = hot )? hot : µ r Γ; T ⊢ e . m ( e ) : D µ ( T-Invoke ) local reasoning 35 / 63
Typing rules - T-Block perfect monotonicity Γ; T ⊢ e 1 . f : C µ Γ; T ⊢ e 2 : C hot Γ; T ⊢ e : T 1 ( T-Block ) Γ; T ⊢ e 1 . f = e 2 ; e : T 1 36 / 63
Typing rules - selection C µ = fieldType ( D , f ) Γ; T ⊢ e : D hot ( T-SelHot ) Γ; T ⊢ e . f : C hot Γ; T ⊢ e : D warm U = fieldType ( D , f ) ( T-SelWarm ) Γ; T ⊢ e . f : U 37 / 63
Authority, flow-insensitivity and strong updates The meta-theory depends on authority: ∀ l ∈ dom (Σ) . Σ( l ) = C µ = ⇒ Σ ′ ( l ) = C µ Σ � Σ ′ 38 / 63
Authority, flow-insensitivity and strong updates The meta-theory depends on authority: ∀ l ∈ dom (Σ) . Σ( l ) = C µ = ⇒ Σ ′ ( l ) = C µ Σ � Σ ′ In a flow-insensitive system without aliasing tracking, it is only safe to perform strong updates of initialization states via the outstanding alias this in a local flow inside the constructor. 38 / 63
Design principles of initialization Each field should have a unique location in Authority the constructor where it is officially initialized. Stack- All fields of an object should be initial- ability ized at the end of the class constructor. Mono- Initialization states cannot be reversed. tonicity Scop- Access to uninitialized objects should ability be controlled by static scoping. 39 / 63
Principled design of constructors To align with the principles, we advocate • class parameters • mandatory field initializers 40 / 63
Principled design of constructors To align with the principles, we advocate • class parameters • mandatory field initializers class RemoteDoc(url: String) { 1 val localFile: String = url.hashCode 2 def name: String = localFile 3 } 4 40 / 63
Languages in industry language year class C(f:Int) var f:Int = e Java 1995 � � C# 2000 � � D 2001 � � Scala 2003 � � � Ceylon 2011 � � Dart 2011 � � Kotlin 2011 � � � TypeScript 2012 � � Crystal 2014 � � Swift 2014 � � 41 / 63
Challenges Reasoning Problem Evaluation Inference Model
What is wrong with type-based approach? To be honest, the reason this approach has likely not yet seen widespread use is that the cost is not commensurate with the benefit. ... For systems programmers, this makes sense. For many other programmers, it would be useless ceremony with no perceived value. — Joe Duffy, “On partially-constructed objects” http://joeduffyblog.com/2010/06/27/on-partiallyconstructed-objects/ 42 / 63
Drawbacks of type-based approach • Annotation overhead • Inadequate to handle traits, inner classes, properties • Does not handle inheritance well • Difficult to integrate in compilers 43 / 63
Type-and-effect systems Γ , x : S ⊢ t : T ! ǫ ( T-Abs ) ǫ Γ ⊢ λ x : S . t : S − → T ! ∅ ǫ 3 Γ ⊢ t 1 : S − → T ! ǫ 1 Γ ⊢ t 2 : S ! ǫ 2 ( T-App ) Γ ⊢ t 1 t 2 : T ! ǫ 1 ∪ ǫ 2 ∪ ǫ 3 Lucassen, J.M., Gifford, D.K. (1988). Polymorphic effect systems. POPL ’88. 44 / 63
Potentials and effects Potentials represent aliasing information of objects possibly under initialization. this | warm [ C ] | cold β ::= π ::= β | π. f | π. m 45 / 63
Potentials and effects Potentials represent aliasing information of objects possibly under initialization. this | warm [ C ] | cold β ::= π ::= β | π. f | π. m Effects represent operations on objects possibly under initialization. π. f ! | π. m ♦ | π ↑ φ ::= 45 / 63
Potentials and effects Potentials represent aliasing information of objects possibly under initialization. this | warm [ C ] | cold β ::= π ::= β | π. f | π. m Effects represent operations on objects possibly under initialization. π. f ! | π. m ♦ | π ↑ φ ::= Γ; C ⊢ e : D ! (Φ , Π) If Π = ∅ , the value of e must be hot. 45 / 63
Expression Typing - Block ensures that e 1 is hot Γ; C ⊢ e 0 : E 0 ! (Φ 0 , Π 0 ) E 1 = fieldType ( E 0 , f ) Γ; C ⊢ e 1 : E 1 ! (Φ 1 , Π 1 ) Γ; C ⊢ e 2 : E 2 ! (Φ 2 , Π 2 ) Φ = Φ 0 ∪ Φ 1 ∪ Φ 2 ∪ Π 1 ↑ Γ; C ⊢ e 0 . f = e 1 ; e 2 : E 2 ! (Φ , Π 2 ) ( T-Block ) 46 / 63
Example – field access effect effects: { this . y ! } class C { 1 var x: Int = this.y 2 var y: Int = 10 3 } 4 47 / 63
Example – potentials class C { 1 var a = this 2 var b = this.a 3 } 4 48 / 63
Example – potentials { this } potentials: effects: ∅ class C { 1 var a = this 2 var b = this.a 3 } 4 48 / 63
Example – potentials { this } potentials: effects: ∅ class C { 1 var a = this 2 var b = this.a 3 } 4 potentials: { this . a } effects: { this . a ! } 48 / 63
Example – potentials { this } potentials: effects: ∅ class C { 1 var a = this 2 var b = this.a 3 } 4 potentials: { this . a } effects: { this . a ! } 48 / 63
Example – method call effects class C { 1 var a = this.m() 2 var b = this 3 def m() = this.b 4 } 5 49 / 63
Example – method call effects potentials: { this . m } { this . m ♦ } effects: class C { 1 var a = this.m() 2 var b = this 3 def m() = this.b 4 } 5 49 / 63
Example – method call effects potentials: { this . m } { this . m ♦ } effects: class C { 1 var a = this.m() 2 var b = this 3 def m() = this.b 4 } 5 { this . b } potentials: effects: { this . b ! } 49 / 63
Example – method call effects potentials: { this . m } { this . m ♦ } effects: class C { 1 var a = this.m() 2 var b = this 3 def m() = this.b 4 } 5 { this . b } potentials: effects: { this . b ! } 49 / 63
Example – promotion effects class C(fun: C => Int) { 1 var x: Int = fun(this) 2 } 3 50 / 63
Example – promotion effects potentials: ∅ effects: { this ↑ } class C(fun: C => Int) { 1 var x: Int = fun(this) 2 } 3 50 / 63
Example – promotion effects potentials: ∅ effects: { this ↑ } class C(fun: C => Int) { 1 var x: Int = fun(this) 2 } 3 Promotion is the same as requiring a value to be hot. 50 / 63
Two-phase checking class C { 1 var a: Int = h() 2 def h(): Int = g() 3 def g(): Int = h() 4 } 5 51 / 63
Two-phase checking class C { 1 var a: Int = h() 2 def h(): Int = g() 3 def g(): Int = h() 4 } 5 First phase method effects potentials { this . g ♦ } { this . g } h { this . h ♦ } { this . h } g 51 / 63
Two-phase checking class C { 1 var a: Int = h() 2 def h(): Int = g() 3 def g(): Int = h() 4 } 5 First phase method effects potentials { this . g ♦ } h { this . g } { this . h ♦ } g { this . h } Second phase fixpoint ( { this . h ♦ } ) = { this . g ♦ , this . h ♦ } 51 / 63
Two-phase checking class C { 1 var a: Int = h() 2 def h(): Int = g() 3 def g(): Int = h() 4 } 5 First phase method effects potentials { this . g ♦ } h { this . g } { this . h ♦ } g { this . h } Second phase fixpoint ( { this . h ♦ } ) = { this . g ♦ , this . h ♦ } ✔ 51 / 63
Cyclic data structures class Parent { 1 val child: Child = new Child(this) 2 child.name // OK 3 } 4 5 class Child( parent: Parent @cold ) { 6 val name = "Jack" 7 } 8 52 / 63
Cyclic data structures potentials: { warm [ Child ] } class Parent { 1 val child: Child = new Child(this) 2 child.name // OK 3 } 4 5 class Child( parent: Parent @cold ) { 6 val name = "Jack" 7 } 8 52 / 63
Full-construction analysis abstract class AbstractFile { 1 def name: String 2 val extension: String = name.substring(4) 3 } 4 5 class RemoteFile(url:String) extends AbstractFile { 6 val localFile: String = url.hashCode 7 def name: String = localFile 8 } 9 53 / 63
Full-construction analysis abstract class AbstractFile { 1 def name: String 2 val extension: String = name.substring(4) 3 } 4 5 class RemoteFile(url:String) extends AbstractFile { 6 val localFile: String = url.hashCode 7 def name: String = localFile 8 } 9 Analysis entry point: primary constructor of concrete classes 53 / 63
Full-construction analysis abstract class AbstractFile { 1 def name: String 2 val extension: String = name.substring(4) 3 } 4 5 class RemoteFile(url:String) extends AbstractFile { 6 val localFile: String = url.hashCode 7 def name: String = localFile 8 } 9 follows super constructor calls 53 / 63
Full-construction analysis resolve virtual call this.name abstract class AbstractFile { 1 def name: String 2 val extension: String = name.substring(4) 3 } 4 5 class RemoteFile(url:String) extends AbstractFile { 6 val localFile: String = url.hashCode 7 def name: String = localFile 8 } 9 53 / 63
Full-construction analysis abstract class AbstractFile { 1 def name: String 2 val extension: String = name.substring(4) 3 } 4 5 class RemoteFile(url:String) extends AbstractFile { 6 val localFile: String = url.hashCode 7 def name: String = localFile 8 } 9 � access uninitialized this.localFile 53 / 63
Functions Function potential: π ::= . . . | Fun (Φ , Π) 54 / 63
Functions potentials of return effects when called Function potential: π ::= . . . | Fun (Φ , Π) 54 / 63
Functions potentials of return effects when called Function potential: π ::= . . . | Fun (Φ , Π) class Rec { 1 val even = (n: Int) => n == 0 || odd(n - 1) 2 val odd = (n: Int) => n == 1 || even(n - 1) 3 val flag: Boolean = odd(6) 4 } 5 54 / 63
Recommend
More recommend