A Type System for Borrowing Permissions
This paper presents a type system designed for managing borrowing permissions in programming, addressing the complexities of aliasing. The proposed system allows for unique, immutable, and shared permissions, helping developers to track references and their capabilities clearly. By characterizing permissions through local borrowing principles, it mitigates the risks of unauthorized access and promotes safe code practices. The paper discusses the trade-offs, benefits, and practical applications of this approach, while providing illustrative examples of its implementation in programming.
A Type System for Borrowing Permissions
E N D
Presentation Transcript
A Type System for Borrowing Permissions Karl Naden, Rob Bocchino Jonathan Aldrich, Kevin Bierhoff POPL – January 27, 2012 School of Computer Science
Aliasing • Trade off of aliases • Pros: flexibility, performance, fields • Cons: Global effects difficult to reason about • Example : Files File x=…; File y=…; … x.close(); … y.read(); x x y y ClosedFile OpenFile OpenFile ClosedFile Illegal Access
Access Permissions • Permission associated with each reference, indicating • Actions that can be taken with this reference • Howmany aliases might exist and their abilities • Examples: • unique (linear/affine) – full access, no other aliases • immutable (non-linear) – non-modifying access, all other aliases non-modifying • shared (non-linear) – many aliases with modifying access x:unique y:immutable OpenFile unique File x=…; immutable File y=…; … x.close(); //close() unique … y.read(); //read() immutable OpenFile ClosedFile Safe
Permission Use Patterns • Borrowing • Make a unique reference temporarilyimmutable • must track aliases to ensure none leftover when regain unique • Fields • Use permissions to objects in fields unique unique immutable … immutable Both essential for use in practice! immutable
Existing Solutions • Borrowing • Characterize Heap Explicitly • Alias Types • Shape Analysis • Fractional Permissions • Both powerful, but difficult to reason about • Fields • Swap (awkward) • Explicit unpacking annotations (flexible but heavyweight) createIterator(immutable(x)>> immutable(x/2)Collection) {…} Iterator it<c,immutable(.5)> = createIterator(c)
Contributions • Local permissions: • Permission-based borrowing • No artificial arithmetic • No explicit heap model • Type system to track permission flow • Counting of aliases under the covers • Field Unpacking • Standard aliasing semantics • No additional syntax for field reads or assignments • Implicit unpacking handled by type system
Outline • Introduction to local Permissions • Using • Checking • Unpacking Fields • In the paper and TR • Conclusion
Outline • Introduction to local Permissions • Using • Checking • Unpacking Fields • In the paper and TR • Conclusion
Local Permissions • Design criteria: Permission-based borrowing • Extend ideas of permissions: Abilities and Guarantees • Local modifier to non-linear permissions • Same access and aliasing guarantees • Additional promise to only create temporary aliases • Cannot store to a field
Owning and Borrowing a Car • Ownership • Owner has unique permission • Selling transfers the unique permission to another Person • Borrowing • A person without a car can temporarily borrow one taking a local immutablepermission • Use • Owners or borrowers can drive a car (local immutable) • Duplicating a key creates an immutable reference class Person { borrow(local immutableCar c) {…} sell(unique >> none Car c, Person p) {…} } class Car { drive() local immutable {…} newKey() immutable {…} }
Borrowing Solution Code Tracked Permissions Person roger = new Person; Person sarah = new Person; Person josh = new Person; unique Car theCar = new Car(); //josh’s car roger.borrow(theCar); //borrow(local immutable) josh.sell(theCar, sarah) //sell(unique >> none, --) Internal Permission Only theCar:unique theCar:borrow(unique,1) theCar:unique theCar:none Typechecks!
Incorrect Use Code Tracked Permissions class CarThiefextends Person { borrow(local immutable Car c) { c.makeKey() //makeKey() immutable } } c:local immutable TypeError – Not enough Permission! • immutable a stronger permission than local immutable • Cannot get an immutable from a local immutable
Correct Use Code Tracked Permissions class Inconsiderate extends Person { borrow(local immutable Car c) { local immutable Car a = c; a.drive()//drive() local immutable this.sister.borrow(c) //borrow(local immutable) //local variable ‘a’ leaves scope } } c:borrow(immutable,1) c:borrow(immutable,1) c:borrow(immutable,1) c:local immutable c:local immutable a:borrow(immutable,1) c:borrow(immutable,2) a:local immutable a:local immutable a:local immutable Typechecks!
Benefits of Local • Programmer can keep thinking in terms of permissions • What kind of permission should be provided? • Do permanent aliases need to be created? • Simple • No fractions or arithmetic • Tracking handled by system, not by programmer • No need to try and visualize/characterize the heap
Outline • Introduction to local Permissions • Using • Checking • Unpacking Fields • In the paper and TR • Conclusion
Fields • Motivation • Using fields creates aliases! • Changes permission of references in fields • Design criteria • Standard aliasing semantics • No extra syntax • Implicit unpacking • Read and assign as normal • Type system tracks unpacking of fields individually
Fields class Garage { unique Car p1; unique Car p2; } josh.sell(g.p1,sarah); //sell(unique>>none,--) • What is the type of ‘g’ after it no longer has a unique permission in the field ‘p1’? • Still unique, • but not a complete Garage • What about the Car in field ‘p2’? Tracked Permissions g:uniqueGarage g:?
Unpacking Unique josh.sell(g.p1,sarah); //sell(unique>>none,--) g.p2.drive(); //drive() local immutable g.p1 = new Car; me.sellG(g,sarah); //sellG(unique>>none garage, Person) Code Tracked Permissions g:(unique;p1:none) Internal Only g:(unique;p1:none, p2:borrow(unique,1)) g:(unique;p1:none) g:uniqueGarage g:(unique;p1:none) g:unique g:none Type Error – g not packed Typechecks!
Unpacking local Code Tracked Permissions borrowGarage (local immutable Garage g) { local immutable Car c = g.p2; c.drive(); //drive() local immutable // c goes out of scope } g:local immutable g:local immutable g:(local immutable; p2:borrow(unique,1)) g:(local immutable; p2:borrow(unique,1)) c:local immutable c:borrow(immutable,1) c:local immutable Typechecks!
Benefits of Implicit Unpacking • Simple • No extra annotations • Natural aliasing semantics
Outline • Introduction to local Permissions • Using • Checking • Unpacking Fields • In the paper and TR • Conclusion
More in the Paper • Complete System • Shared permissions • Control flow (match) • Formal System • typing rules • Soundness claims • Proof in the TR • Issues with published system • Several inconsistencies found post-publication • TR details problems and includes updated rules and proof
Conclusion • Contributions • Local permissions support borrowing in consistent simple manner • No complex fractions • No heap visualizations • Fields unpacked implicitly • Normal aliasing semantics • No extra annotations • Sound type system tracks access permissions • Restore unique permission after borrowing • Tracks unpacked fields • Questions?