I have already add 2 RFCs related to topic, but they are fluid in changes and I've already close 2 RFC related to topic (which I changed several times). So, people admit me to find feedback here, your ideas are welcomed, as your alternatives and so on
UPD: Partial Types (v3)
Partial Types (v2) (rfc#3426) and Partial Mutability (rfc#3428)
This is a universal and full solution to "partial borrow" problem.
It is based on fact, that on Product Types (PT = T1 and T2 and T3
) like Strcts and Tuples we can get a mathematical guarantee, that using simultaneously variable of partial typed, it multiple partial references and partial borrowing is as safe as using them at a sequence.
And since it is a guarantee by type , not by values , it has zero cost in binary! Any type error is a compiler error, so no errors in the runtime.
Sum Types (ST = T1 or T2 or T3
) like Enum are not part of this proposal.
Simple implicit rules on types:
context Partial types | desugar |
---|---|
let r : Type = ... |
let r : Type.%full = ... |
let r = var |
let r = var.%max |
let r = & var |
let r = & var.%max |
let r = &mut var |
let r = &mut var.%max |
return var |
return var.%exact |
return & var |
return & var.%exact |
return &mut var |
return &mut var.%exact |
self.call(&mut var) |
self.call(&mut var.%arg) |
let var = S{fld1:val1,..} |
let var = S{%permit fld1:val1,..}.%max |
let var = S{} |
let var = S{%miss fld1,..}.%max |
Simple implicit rules for mutability:
context mut /mix
|
desugar |
---|---|
let r = &mut var |
let r = &mut.%max var |
self.call(&mut var) |
self.call(&mut.%arg var) |
let mut var = .. |
let mut.%full var = .. |
let mut var : .. = .. |
let mut.%lift var : .. = .. |
let .. : &mut Type = .. |
let .. : &mut.%full Type = .. |
let .. : &mix Type = .. |
let .. : &mut.%type Type = .. |
let .. : mix Type = .. |
let .. : mut.%type Type = .. |
Simple implicit Mix uses:
context types & mut | desugar |
---|---|
let r = & var |
let r = & var.%max |
let r = &mut var |
let r = &mut.%max var.%max |
return & var |
return & var.%exact |
return &mut var |
return &mut.%max var.%exact |
self.call(& var) |
self.call(& var.%arg) |
self.call(&mut var) |
self.call(&mut.%arg var.%arg) |
Here examples of partial types:
struct Point {x: f64, y: f64, was_x: f64, was_y: f64}
let mut p1_full = Point {x: 1.0, y: 2.0, was_x: 4.0, was_y: 5.0};
// p1_full : Point;
let p_just_x = Point {x: 1.0};
// partial initializing
// p_just_x : Point.%{x, %unfill};
let ref_p_just_x = & p_just_x;
// partial referencing
// ref_p_justx : & Point.%{x};
// late initialize unfilled fields
p_just_x.y let= 6.0;
// p_just_x : Point.%{x, y, %unfill};
p_just_x.was_y let= 14.0;
// p_just_x : Point.%{x, y, was_y, %unfill};
p_just_x.was_x let= 76.0;
// p_just_x : Point.%full;
// p_just_x : Point;
// partial parameters
fn x_restore(&mut p1 : &mut Point.%{was_x, %any}, & p2 : & Point.%{x, %any}) {
*p1.x = *p2.was_x;
}
// partial arguments
x_restore(&mut p1_full, & p1_full);
And examples of partial mutable variables and references:
let mut p1 : mut.%{x,y} Point = Point {x:1.0, y:2.0, was_x: 4.0, was_y: 5.0, state: 12.0};
// p1 : mut.%{x,y} Point
let mut p2 : mut.%{x,was_x} Point = Point {x:1.0, y:2.0, was_x: 4.0, was_y: 5.0, state: 12.0};
// p2 : mut.%{x,was_x} Point
let ref_p1 = &mut p1;
// ref_p1 : &mut.%{x, y} Point
let refnr_p2 = &mut.%{x} p2;
// refnr_p2 : &mut.%{x} Point
fn vz_restore (&mut p : &mut.%{was_x} Point2) {
*p.x = *p.was_x;
}
vz_restore(&mut p2);
pub fn mx_rstate(&mut p : &mix Point.%{mut x, state, %any}) { /* ... */ }
// mixed partiality of type and mutability