370 likes | 392 Views
This paper introduces a powerful static system called Pedigree Type Inference that incorporates ownership type systems with parameterized classes. It provides a simple and intuitive syntax for parametric polymorphism and demonstrates an example program in Pedigree Types.
E N D
Pedigree Types Yu David Liu, Johns Hopkins University / SUNY Binghamton Scott F. Smith, Johns Hopkins University July 7, 2008 @ IWACO’08
Ownership Type Systems Ownership with ParameterizedClasses Universe Types Simple and Intuitive Syntax Parametric Polymorphism Pedigree Types and Inference
An Example Program in Pedigree Types(and in Universe Types) class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } } class Controller { … } class Button { … } * The two pedigrees above are identical to “peer” and “rep” in Universe Types.
The Example in UML :Main v1:View c1:Contoller b1:Button * The top-down direction indicates ownership.
The General Form of Pedigrees Good case: sibling = (parent)^1 (child)^1 Good case: child = (parent)^0 (child)^1 Bad case: nephew = (parent)^1 (child)^2 Bad case: grandchild = (parent)^0 (child)^2 Good case: self = (parent)^0 (child)^0 Good case: parent = (parent)^1 (child)^0 (parent)^a (child)^b where a>=0, b = 0 or 1
class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } } class Controller { … } class Button { … }
class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } } class Controller { … } class Button{ parent View container; Controller ctrl; Button(Contoller ctrl, View v) { this.ctrl = ctrl; this.container = v; } void refresh () { … container.refresh();} }
Is (parent)^10 (child)^1 Useful ? “nai, nai!” thus spoke the inference algorithm. * “nai” means “yes” in Greek.
class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } } class Controller { … } class Button{ parent View container; Controller ctrl; Button(Contoller ctrl, View v) { this.ctrl = ctrl; this.container = v; } void refresh () { … container.refresh();} }
Options for the Omitted Pedigree • Treat it as “sibling”.
Defaulting as “sibling” :Main v1:View c1:Contoller b1:Button c1 is an “uncle” of b1, not a “sibling”.
Options for the Omitted Pedigree • Treat it as “sibling”. • Treat it as “world”, i.e. shared by everyone.
Defaulting as “world” c1: Controller :Main c2: Controller s1:System s2:System v1:View c1: Controller v2:View c2: Controller b1:Button b2:Button The encapsulation of s1 and s2 is broken!
Options for the Omitted Pedigree • Treat it as “sibling”. • Treat it as “world”, i.e. shared by everyone. • Treat it as some pedigree that can be reclaimed by dynamic casting (a “top type” pedigree).
Options for the Omitted Pedigree • Treat it as “sibling”. • Treat it as “world”, i.e. shared by everyone. • Treat it as some pedigree that can be reclaimed by dynamic casting (a “top type” pedigree). • Treat it as some pedigree that can be inferred statically.
Pedigree Types A constraint-based type system to embed heap objects onto the ownership tree reusing the vocabulary of human genealogy: • Declare a pedigree only if you care. • Given a reference with its pedigree omitted, it is equivalent to think of it having a pedigree of (parent)^a (child)^b, where a and b are type variables to be solved by the inference algorithm, where a ranges over non-negative integers and b ranges over {0, 1}. • A typechecked program means an ownership tree exists to embed heap objects. • A type error means an “incest”-free tree cannot be constructed.
Pedigree Type Inference A powerful static system with the following features:
Pedigree Type Inference A powerful static system with the following features: • It is parametrically polymorphic.
The Need for Polymorphism :Main v1:View c1:Contoller b1:Button d: Dialog b2:Button
Pedigree Type Inference A powerful static system with the following features: • It is parametrically polymorphic. • The technique: thinking about ML-style let-polymorphism in OO languages.
class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } } class Controller { … } class Button{ parent View container; Controller ctrl; Button(Contoller ctrl, View v) { this.ctrl = ctrl; this.container = v; } void refresh () { … container.refresh();} }
− ∨ class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } } class Controller { … } class Button{ parent View container; (parent)^a1 (child)^b1 Controller ctrl; Button(Contoller ctrl, View v) { this.ctrl = ctrl; this.container = v; } void refresh () { … container.refresh();} } a1, b1
Pedigree Type Inference A powerful static system with the following features: • It is parametrically polymorphic. • The technique: thinking about ML-style let-polymorphism in OO languages. • Indirect references are polymorphically treated as well.
− ∨ class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } } class Controller { … } class Button{ parent View container; (parent)^a1 (child)^b1 Controller ctrl; Button(Contoller ctrl, View v) { this.ctrl = ctrl; this.container = v; } void refresh () { … container.refresh();} } a1, b1
− ∨ class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } Timer t; } class Controller { … } class Button{ parent View container; (parent)^a1 (child)^b1 Controller ctrl; Button(Contoller ctrl, View v) { this.ctrl = ctrl; this.container = v; } void refresh () { … container.refresh();} } a1, b1
− ∨ class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } (parent)^a2 (child)^b2 Timer t; } class Controller { … } class Button{ parent View container; (parent)^a1 (child)^b1 Controller ctrl; Button(Contoller ctrl, View v) { this.ctrl = ctrl; this.container = v; } void refresh () { … container.refresh();} } a1, b1, a2, b2
Pedigree Type Inference A powerful static system with the following features: • It is parametrically polymorphic. • It correctly handles mutually recursive classes.
Pedigree Type Inference A powerful static system with the following features: • It is parametrically polymorphic. • It correctly handles mutually recursive classes. • It is inter-procedural.
class Main { public static void main (String[] args) { View v1 = new View(); Controller c1 = new Controller(); } } class View { sibling Controller ctrl; View() { Button b1 = new child Button(ctrl, this); } void refresh() { … } } class Controller { … } class Button{ parent View container; Controller ctrl; Button(Contoller ctrl, View v) { this.ctrl = ctrl; this.container = v; } void refresh () { … container.refresh();} }
Pedigree Type Inference A powerful static system with the following features: • It is parametrically polymorphic. • It correctly handles mutually recursive classes. • It is inter-procedural. • It allows for flexible structural subtyping with recursive object types.
Pedigree Type Inference A powerful static system with the following features: • It is parametrically polymorphic. • It correctly handles mutually recursive classes. • It is inter-procedural. • It allows for flexible structural subtyping with recursive object types. • Standard object types are handled via μ- types [Amadio & Cardelli]. • Pedigree subsumption is also allowed: • self <: sibling • parent <: uncle • (parent)^a (child)^b <: (parent)^(a+1) (child)^(b+1)
Pedigree Type Inference A powerful static system with the following features: • It is parametrically polymorphic. • It correctly handles mutually recursive classes. • It is inter-procedural. • It allows for flexible structural subtyping with recursive object types. • It is decidable: reduced to finding non-negative solutions to linear diophantine equations, a well-studied problem.
Formal Results The type system is rigorously defined on top of a Java-like object model, with following properties formally proved: • The type system is sound (proved via subject reduction and progress). • Deep ownership preservation: any reference at run time has to point to an object with a pedigree (parent)^a (child)^b where a>=0 and b = 0 or 1. • Shape enforcement: if a reference is declared to have pedigree (parent)^a (child)^b, then at run time it points to an object with pedigree (parent)^a (child)^b, or a pedigree subsumed by it.
Extensions We believe Pedigree Types can be extended with the following features (more discussions in the paper): • “owner-as-modifier” ownership tree: in our terms, it means to allow (parent)^a (child)^b where a>=0 and b>1, as long as the reference is read-only. • Selective exposure: allow programmer-defined policies for exceptional cases, like “allow access from my grandparent”. • Opt-out references. • Dynamic class loading.
Related Work • Universe Types (UT) • Similarity in syntax: “peer” and “rep”. • UT features we do not have: “owner-as-modifiers”, generics, ownership transfer. • Our features: parametric polymorphism for omitted pedigrees; a more general form of pedigrees; static inference. • Ownership with Parameterized Classes • Similarity in expressiveness: parametric polymorphism. • Numerous extension features we do not cover (yet): effect encapsulation, interaction with concurrency, selective exposure, multiple ownership. • Our features: minimal declarations (declare only when you care!), polymorphic inference (sound, decidable, inter-procedural, consideration for realistic OO features such as recursive types and classes).
Concluding Remarks • Programmability: very low-maintenance declaration system with minimal extension to the Java object model. • Expressiveness: on par with existing ownership systems using parameterized classes (additions: “self”, “parent”); a powerful inference algorithm. • Correctness: type soundness, ownership enforcement, shape enforcement. Future work: implementation, advanced features such as their impact on concurrency.