From 6548611f1e4550ae79743fb8887c7d09265e2a95 Mon Sep 17 00:00:00 2001 From: VitWW <130038091+VitWW@users.noreply.github.com> Date: Fri, 6 Dec 2024 18:51:02 +0200 Subject: [PATCH 1/5] create partial_types --- text/0000-partial_types.md | 395 +++++++++++++++++++++++++++++++++++++ 1 file changed, 395 insertions(+) create mode 100644 text/0000-partial_types.md diff --git a/text/0000-partial_types.md b/text/0000-partial_types.md new file mode 100644 index 00000000000..4e1c8c942ca --- /dev/null +++ b/text/0000-partial_types.md @@ -0,0 +1,395 @@ +- Feature Name: `partial_types` +- Start Date: 2024-12-06 +- RFC PR: [rust-lang/rfcs#3736](https://github.com/rust-lang/rfcs/pull/3736) +- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) + + +# Summary +[summary]: #summary + +This proposal is universal flexible tool to work **safe** and **zero cost binary** with partial Structs and Tuples in parameters, arguments, references and borrows. + +Advantages: maximum type safety, maximum type control guarantee, no ambiguities, zero-cost-binary, flexibility, usability and universality. + + +# Motivation +[motivation]: #motivation + +Partial Types proposal is a generalization on "partial borrowing"-like proposals. Safe, Flexible controllable partial parameters for functions and partial consumption (including partial borrowing) are highly needed. + +Partial Types extension gives to Product Types (`PT = T1 and T2 and T3 and ..`), Structs and Tuples first of all, a good **mathematical guarantee** to borrow-checker that borrowing the whole variable with partial type and pretending to borrow just permitted fields is **fully safe** (without using `unsafe`). +```rust +struct StructABC { a: u32, b: i64, c: f32, } + +// function with partial parameter Struct +fn ref_a (s : & StructABC.{a}) -> &u32 { + &s.a +} + +let s = StructABC {a: 4, b: 7, c: 0.0}; + +// partial expression at argument +let sa = ref_a(& s.{a}); +``` + +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. + +This extension is not only fully backward-compatible, but is fully forward-compatible! Forward-compatibility is an ability to use updated functions old way. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +Partiality of type (or partial type access) is written as `Path.{fld1, fld2, fld3}` after Path (Type name), where `fld1`, `fld2`, .. are only permitted read (and maybe to write if variable is `mut`) fields of this type, the rest of fields are forbidden to read and write and unset. + +But the same time fields that are forbidden to read and write it is totally Ok to borrow, re-borrow, move, re-move, without any consequences - because the Compiler guarantee that in safe mode it is impossible to use such fields. It is a compile error if someone try to access it. + +## Partial Structs and Tuples + +For Product Types `PT = T1 and T2 and T3 and ..`), for structs, tuples we need not only partiality of a type, but also "partial access" expression: `Expr .{fld1, fld2, fld3}`, where `fld1`, `fld2`, .. are permitted fields of this type, the rest of fields are forbidden. + +One step to partial borrows Structs and Tuples. +```rust +struct Point { + x: f64, + y: f64, + was_x: f64, + was_y: f64, + state : f64, +} +let mut p1 = Point {x:1.0, y:2.0, was_x: 4.0, was_y: 5.0, state: 12.0}; + // p1 : Point + +let ref_p1was = &mut p1.{wax_x, was_y}; + // ref_p1was : &mut Point.{was_x, was_y} + +let ref_p1now = &mut p1.{x, y}; + // ref_p1now : &mut Point.{x, y} +``` +It is simple and will be possible. + +It is easy to write functions, which consume partial parameters: +```rust +impl Point { + fn ref_x (self : & Self.{x}) -> &f64 { + &self.x + } + + fn refmut_y (self : &mut Self.{y}) -> &mut f64 { + &mut self.y + } +} +let ref_p1x = p1.ref_x(); +let refmut_p1y = p1.refmut_y(); +``` +It is expected, that `self` is **always** cut partiality of argument by same partiality as self-parameter by partial expression before use (even if implicit rules are off)! + +Pseudo-rust: +```rust +fn ref_xy (self : & Self.{ x, y}) -> &f64 { + /* */ +} + +p1.ref_xy(); +// which "desugar" +Point::ref_xy(& p1.{x, y}); +``` + +Product-Typed argument type must match with function parameter type or argument type could has **more** permitted partiality then parameter type. +```rust +// Struct ~ Product Type +struct S4 {a : i32, b : i32, c : i32, d : i32} + +fn do_sab(s : S4.{a, b}) { /* .. */ } + +let s = S4 {a: 6, b: 7, c: 8, d: 9}; + +do_sab(s.{a}); // s.{a} - error +do_sab(s.{b}); // s.{b} - error +do_sab(s.{a, b}); // s.{a, b} - Ok +do_sab(s.{a, b, c}); // s.{a, b, c} - Ok +do_sab(s); // s.{*} - Ok +``` + + +# Reference-level explanation + +The core Idea of this proposal is "Proxy Borrowing" - we borrow the whole variable, but borrow-checker pretends it borrow just permitted/allowed fields. + +Automatically Type-checker gives a mathematical guarantee, because all denied/forbidden fields remain intact! + +And this mean, that Proxy Borrowing borrowing is fully **safe** and _zero cost_ in binary. + +## Proxy Borrowing + +Borrowing rules for partial types: + +`PermittedField` field borrowing rules are ordinary Rust rules. New variable borrows the whole variable (with partial type), but checker pretends it borrows just permitted fields of this variable. + +Not-`PermittedField` filed is always is ready to borrow regardless if origin field is denied(by move, by reference, by borrow). + +When we write a code for full or partial borrow, the link of object itself returns, but borrow-checker checks to borrow of permitted fields only. + +This new mechanism of is simple and universal. + +```rust +struct S4 {a : i32, b : i32, c : i32, d : i32} +let s = S4 {a : 5, b: 6, c: 7, d: 8}; + // s : S4 + +let r_sd = & s.{d}; + // r_sd : & S4.{d} + // + // borrow-checker check just for &s.d + +let mut mr_sabc = &mut s.{a, b, c}; + // mr_sabc : &mut S4.{a, b, c} + // + // borrow-checkercheck just for &mut s.a, &mut s.b, &mut s.c + +let rr_sbc = & mr_sabc.{b, c}; + // rr_sbc : && S4.{b, c} + // + // borrow-checker check just for &mr_sabc.b, &mr_sabc.c + +let mut mrr_sa = &mut mr_sabc.{a}; + // mrr_sa : &&mut S4.{a} + // + // borrow-checker check just for &mut mr_sabc.a +``` + +## Syntax + +Second, but still important - syntax. + +### Partiality Syntax + +Minimal Partiality we could write: +``` +Partiality: .{ PartialFields* } +PartialFields: PermittedField (, PermittedField )* ,? +PermittedField: IDENTIFIER | TUPLE_INDEX +``` + +### Partial Struct syntax + +Syntax is needed to Struct Type - is update `TypePath` +``` +TypePath: ::? TypePathSegment (:: TypePathSegment)* Partiality? +``` + +### Partial Tuple syntax + +For Tuple Type we need to update `TupleType` +``` +TupleType: ( ) | ( ( Type , )+ Type? ) Partiality? +``` + +### Partial Expression syntax + +For Expression we need create new kind of Expression: +``` +PartialExpression: Expression Partiality +``` + +and include it into `ExpressionWithoutBdeny`: +``` +ExpressionWithoutBdeny: ... | FieldExpression | PartialExpression | ... +``` + + +## Logic Scheme + +Third, but still important - Logic Scheme. + +For pseudo-rust we suppose, partiality is a `HashSet` of permitted field-names. + +Common rules: +```rust +fn bar(v : SomeType.{'type_prtlty}) +{ /* .. */ } + +let v : SomeType.{'var_prtlty}; +``` +Then: + +(1) If `SomeType` is not supported type (neither Struct nor Tuple) then Error. + +(2) If partiality has no extra field-names `type_prtlty.is_subset(full_prtlty)` it compiles, otherwise Error. + +(3) If `var_prtlty.is_subset(full_prtlty)` it compiles, otherwise Error. + +(4) If `type_prtlty.is_empty()` or `var_prtlty.is_empty()` (if they are explicitly written as '`.{}`') then Error + +### Partial Struct and Tuples Logic Scheme + + +Let we have (pseudo-rust) and `st_param_prtlty` and `st_arg_prtlty` are `HashSet` of permitted field-names: +```rust +fn bar(s : SomeStructOrTuple.{'st_param_prtlty}) +{ /* .. */ } + +let s : SomeStructOrTuple.{'st_arg_prtlty}; +bar(s); + +let rsp = & s.{'expr_prtlty}; + +impl SomeStructOrTuple.{'st_impl_prtlty} { + fn foo(self : Self.{'st_slf_prtlty}) + { /* .. */ } +} + +s.foo(); +// (4) desugars into: +SomeStructOrTuple.{'st_impl_prtlty}::foo(s.{'st_slf_prtlty}); +``` +Then: + +(1) If `st_arg_prtlty.is_superset(st_param_prtlty)` it compiles, otherwise Error. + +(2) If `expr_prtlty.is_subset(st_arg_prtlty)` it compiles, otherwise Error. + +(3) If `st_slf_prtlty.is_subset(st_impl_prtlty)` it compiles, otherwise Error. + +(4) Updating desugaring for `self` (and `Rhs`) variables. + +Desugaring `s.foo()` into `SomeStructOrTuple.{'st_impl_prtlty}::foo(s.{'st_slf_prtlty})` . + +(5) It has **no sense** to have several implementation of same product-type and different partiality. + +(6) Anyway let we have several implementations for same type, but different partiality. And `all_st_impl_prtlty` is an `array` of each `st_impl_prtlty`. + +If `all_st_impl_prtlty.iter().any(|&sip| st_arg_prtlty.is_subset(sip))` it compiles, otherwise Error. + +(8) If `1 == all_st_impl_prtlty.iter().fold(0, |acc, &sip| if st_arg_prtlty.is_subset(sip) {acc+1} else {acc})` it compiles, otherwise ?Error. + +We expect that just one "implementation" partiality is match and we choose it for calling a method. + + +# Drawbacks +[drawbacks]: #drawbacks + +- it is definitely not a minor change +- type system became much more complicated + + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + + A lot of proposals that are alternatives to Partial Product Types in a whole: + - Partial Types (v2) [#3426](https://github.com/rust-lang/rfcs/pull/3426) + - Partial Mutability [#3428](https://github.com/rust-lang/rfcs/pull/3428) + - Partial Types [#3420](https://github.com/rust-lang/rfcs/pull/3420) + - Partial borrowing [issue#1215](https://github.com/rust-lang/rfcs/issues/1215) + - View patterns [internals#16879](https://internals.rust-lang.org/t/view-types-based-on-pattern-matching/16879) + - Permissions [#3380](https://github.com/rust-lang/rfcs/pull/3380) + - Fields in Traits [#1546](https://github.com/rust-lang/rfcs/pull/1546) + - ImplFields [issue#3269](https://github.com/rust-lang/rfcs/issues/3269) + + +# Prior art +[prior-art]: #prior-art + +Most languages don't have such strict rules for references and links as Rust, so this feature is almost unnecessary for them. + + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +It is better to have 2 ways to write partiality: a list with just "allowed" fields and just "forbidden" fields for better ergonomics + +```rust +let t1 = s10.{fld1, fld2, fld3, fld4, fld5, fld6, fld7, fld8}; +// just "allowed" fields +// t1 : S10.{fld1, fld2, fld3, fld4, fld5, fld6, fld7, fld8} + +let t2 = S10.{off fld9, fld10}; +// just "forbidden" fields +// t2 : S10.{fld1, fld2, fld3, fld4, fld5, fld6, fld7, fld8} +``` + + +# Future possibilities +[future-possibilities]: #future-possibilities + +Adding "partiality" opens wide variety of future possibilities. + + +## Partial Mutability + +*partly independent sub-proposal*. + +For full flexibility of using partial borrowing partial mutability is needed! + +For Product Partial Types (structs, tuples) we use "partial mutability" expression: `mut .{fld1, fld2, ..}`, where `fld1`, `fld2`, .. are mutable fields of this type, the rest of fields are immutable(constant). + +Partly mutable variables become possible for Product Partial Types: +```rust +struct S4 {a : i32, b : i32, c : i32, d : i32} + +let mut.{a} s_ma = S4 {a: 6, b: 7, c: 8, d: 9}; +let mut.{b, c} s_mbc = S4 {a: 6, b: 7, c: 8, d: 9}; +let mut.{a, c, d} s_macd = S4 {a: 6, b: 7, c: 8, d: 9}; +``` + +It is also possible to make partial-mutable references. + +Not-`PermittedField` filed is always is ready to mutable and immutable borrow regardless if origin field is denied(by move, by reference, by borrow), is visible, is mutable: +```rust + fn mab_s(s : &mut.{a,b} S4) + { /* ... */ } + + mab_s(&mut.{a,b} s_macd); +``` +It is expected, that `&mut.{..}` is a third type of borrowing! + +Example with full flexibility of using partial borrowing together with partial mutability + +```rust +impl Point { + pub fn mx_rstate(self : &mut.{x} Self.{x, state}) + { /* ... */ } + + pub fn my_rstate(self : &mut.{y} Self.{y, state}) + { /* ... */ } + + pub fn mxy_rstate(self : &mut.{x,y} Self.{x, y, state}) { + /* ... */ + self.{x, state}.mx_rstate(); // explicit + self.mx_rstate(); // same implicit + /* ... */ + self.{y, state}.my_rstate(); // explicit + self.my_rstate(); // same implicit + /* ... */ + } +} +``` + + +## Explicit Off Fields + +This extension is not a mandatory. Tuple type has "naked" structure, so it would be handy have more pretty visuals, instead of mark all permitted fields in "partiality", write `off` before denied field. +```rust +let t :: (i32, &u64, f64, u8).{1,3}; +// same as +let t :: (off i32, &u64, off f64, u8); +``` + +This extension is not just pretty, but useful for Tuples. + + +## Partial Types to Sum Types (Enums) + +Partial Types extension gives to Sum Types (`ST = T1 or T2 or T3 or ..`), Enums first of all, a good tool for "partial functions". +```rust +enum EnumABC { A(u32), B(i64), C(f32), } + +// function with partial parameter Enum +fn print_A(a: EnumABC.{A}) { + println!("a is {}", a.0); +} + +let ea = EnumABC::A(7); +// ea : EnumABC.{A} inferred + +print_A(ea); +``` From 84fd4cc91dda7dada65c03387562300d38f6f1f4 Mon Sep 17 00:00:00 2001 From: VitWW <130038091+VitWW@users.noreply.github.com> Date: Sat, 7 Dec 2024 00:38:55 +0200 Subject: [PATCH 2/5] update --- text/0000-partial_types.md | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/text/0000-partial_types.md b/text/0000-partial_types.md index 4e1c8c942ca..33d2b41bb4d 100644 --- a/text/0000-partial_types.md +++ b/text/0000-partial_types.md @@ -21,14 +21,14 @@ Partial Types extension gives to Product Types (`PT = T1 and T2 and T3 and ..`), ```rust struct StructABC { a: u32, b: i64, c: f32, } -// function with partial parameter Struct +// function with partial parameter fn ref_a (s : & StructABC.{a}) -> &u32 { &s.a } let s = StructABC {a: 4, b: 7, c: 0.0}; -// partial expression at argument +// partial expression, partial reference and partial argument let sa = ref_a(& s.{a}); ``` @@ -45,7 +45,7 @@ But the same time fields that are forbidden to read and write it is totally Ok t ## Partial Structs and Tuples -For Product Types `PT = T1 and T2 and T3 and ..`), for structs, tuples we need not only partiality of a type, but also "partial access" expression: `Expr .{fld1, fld2, fld3}`, where `fld1`, `fld2`, .. are permitted fields of this type, the rest of fields are forbidden. +For Product Types `PT = T1 and T2 and T3 and ..`), for structs, tuples we need not only partiality of a type, but also **"partial access" expression**: `Expr .{fld1, fld2, fld3}`, where `fld1`, `fld2`, .. are permitted fields of this type, the rest of fields are forbidden. One step to partial borrows Structs and Tuples. ```rust @@ -81,6 +81,9 @@ impl Point { let ref_p1x = p1.ref_x(); let refmut_p1y = p1.refmut_y(); ``` +Here, since the methods' `self` types are partial references, only the needed fields are borrowed, so the call to `refmut_y` doesn't invalidate `ref_p1x`. + + It is expected, that `self` is **always** cut partiality of argument by same partiality as self-parameter by partial expression before use (even if implicit rules are off)! Pseudo-rust: @@ -166,10 +169,29 @@ Second, but still important - syntax. Minimal Partiality we could write: ``` Partiality: .{ PartialFields* } -PartialFields: PermittedField (, PermittedField )* ,? +PartialFields: PartialField (, PartialField )* ,? +PartialField: PermittedField PermittedField: IDENTIFIER | TUPLE_INDEX ``` +If we wish to describe partial structs with partial structs inside, we must have a bit more complex Partiality: + +``` +PartialField: PermittedField Partiality? +``` + +Example: +```rust +struct Foo { a: i32, bar: Bar, } + +struct Bar { b: f32, c: String, } + +impl Foo { + fn baz(&self.{a, bar.c}) { + } +} +``` + ### Partial Struct syntax Syntax is needed to Struct Type - is update `TypePath` @@ -220,6 +242,9 @@ Then: (4) If `type_prtlty.is_empty()` or `var_prtlty.is_empty()` (if they are explicitly written as '`.{}`') then Error +Maybe (4) is too strong limitation and it is handy to check just the address for comparison and wasn't allowed to read/write any fields. +Then, (4) is a part of "Unresolved questions" + ### Partial Struct and Tuples Logic Scheme From 891822e8660efc3b706cf46631cae63fec560fc3 Mon Sep 17 00:00:00 2001 From: VitWW <130038091+VitWW@users.noreply.github.com> Date: Fri, 13 Dec 2024 17:15:02 +0200 Subject: [PATCH 3/5] add inverse partiality --- text/0000-partial_types.md | 52 +++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/text/0000-partial_types.md b/text/0000-partial_types.md index 33d2b41bb4d..6d5136925ff 100644 --- a/text/0000-partial_types.md +++ b/text/0000-partial_types.md @@ -39,13 +39,39 @@ This extension is not only fully backward-compatible, but is fully forward-compa # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -Partiality of type (or partial type access) is written as `Path.{fld1, fld2, fld3}` after Path (Type name), where `fld1`, `fld2`, .. are only permitted read (and maybe to write if variable is `mut`) fields of this type, the rest of fields are forbidden to read and write and unset. +Partiality of type (or partial type access) is written as `Path.{fld1, fld2, fld3}` after Path (Type name), where `fld1`, `fld2`, .. are only permitted to read (and maybe to write if variable is `mut`) fields of this type regardless of visibility, the rest of fields are forbidden to read and write and unset. + +Inverse partiality of type (or partial type access) is written as `Path.{off fld1, fld2, fld3}` after Path (Type name), where `off` is a new keyword and `fld1`, `fld2`, .. are only forbidden to read fields of this type regardless of visibility, the rest of fields are permitted to read (and maybe write) and unset. But the same time fields that are forbidden to read and write it is totally Ok to borrow, re-borrow, move, re-move, without any consequences - because the Compiler guarantee that in safe mode it is impossible to use such fields. It is a compile error if someone try to access it. ## Partial Structs and Tuples -For Product Types `PT = T1 and T2 and T3 and ..`), for structs, tuples we need not only partiality of a type, but also **"partial access" expression**: `Expr .{fld1, fld2, fld3}`, where `fld1`, `fld2`, .. are permitted fields of this type, the rest of fields are forbidden. +For Product Types `PT = T1 and T2 and T3 and ..`), for structs, tuples we need not only partiality of a type, but also **"partial access" expression**: `Expr .{fld1, fld2, fld3}`, where `fld1`, `fld2`, .. are permitted fields of this type regardless of visibility, the rest of fields are forbidden. + +Alternative expression is `Expr .{off fld1, fld2, fld3}`, where `fld1`, `fld2`, .. are forbidden fields of this type regardless of visibility, the rest of fields are permitted. Alternative syntax is useful to avoid of using private fields and if a list of permitted fields is much longer then list of forbidden fields. + +Advantages of using inverse partiality: for better ergonomics and avoid using private fields names directly +```rust +// // For better ergonomics +let t1 = s10.{fld1, fld2, fld3, fld4, fld5, fld6, fld7, fld8}; +// just "allowed" fields +// t1 : S10.{fld1, fld2, fld3, fld4, fld5, fld6, fld7, fld8} + +let t2 = s10.{off fld9, fld10}; +// just "forbidden" fields +// t2 : S10.{fld1, fld2, fld3, fld4, fld5, fld6, fld7, fld8} + + +// // For avoid using private fields names directly +let fpubs = &foo.{pubfld1, pubfld2, pubfld3,}; +// just "allowed" fields +// fpubs : Foo.{pubfld1, pubfld2, pubfld3,} + +let fprivs = &foo.{off pubfld1, pubfld2, pubfld3,}; +// just "forbidden" fields +// fprivs : Foo.{privfld1, privfld2, privfld3, privfld4, privfld5,} +``` One step to partial borrows Structs and Tuples. ```rust @@ -169,28 +195,30 @@ Second, but still important - syntax. Minimal Partiality we could write: ``` Partiality: .{ PartialFields* } -PartialFields: PartialField (, PartialField )* ,? +PartialFields: PartialField1 (, PartialField )* ,? +PartialField1: off? PartialField PartialField: PermittedField PermittedField: IDENTIFIER | TUPLE_INDEX ``` -If we wish to describe partial structs with partial structs inside, we must have a bit more complex Partiality: +If we wish to describe nested partial structs, we must have a bit more complex Partiality: ``` PartialField: PermittedField Partiality? ``` -Example: +Example of using nested partiality: ```rust struct Foo { a: i32, bar: Bar, } struct Bar { b: f32, c: String, } impl Foo { - fn baz(&self.{a, bar.c}) { + fn baz(&self.{a, bar.{c}}) { } } ``` +`off` (or we could choose another name) is a local keyword for syntax of inverse partiality. ### Partial Struct syntax @@ -320,17 +348,7 @@ Most languages don't have such strict rules for references and links as Rust, so # Unresolved questions [unresolved-questions]: #unresolved-questions -It is better to have 2 ways to write partiality: a list with just "allowed" fields and just "forbidden" fields for better ergonomics - -```rust -let t1 = s10.{fld1, fld2, fld3, fld4, fld5, fld6, fld7, fld8}; -// just "allowed" fields -// t1 : S10.{fld1, fld2, fld3, fld4, fld5, fld6, fld7, fld8} - -let t2 = S10.{off fld9, fld10}; -// just "forbidden" fields -// t2 : S10.{fld1, fld2, fld3, fld4, fld5, fld6, fld7, fld8} -``` +Not found yet. # Future possibilities From b46f5152a06591c4fe8bb3107b29f4e6bfe885e8 Mon Sep 17 00:00:00 2001 From: VitWW <130038091+VitWW@users.noreply.github.com> Date: Fri, 13 Dec 2024 17:53:18 +0200 Subject: [PATCH 4/5] add unresolved --- text/0000-partial_types.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/text/0000-partial_types.md b/text/0000-partial_types.md index 6d5136925ff..5b140219b99 100644 --- a/text/0000-partial_types.md +++ b/text/0000-partial_types.md @@ -348,8 +348,11 @@ Most languages don't have such strict rules for references and links as Rust, so # Unresolved questions [unresolved-questions]: #unresolved-questions -Not found yet. - +It would be wonderfull to have some pseudo-field, which meant "all not public(private) fields". Maybe `!pub` is Ok. +```rust +let fprivs = &foo.{!pub}; +// fprivs : Foo.{privfld1, privfld2, privfld3, privfld4, privfld5,} +``` # Future possibilities [future-possibilities]: #future-possibilities From 381b6e5cece1aae6aee89c8cf46dc1bb8e2988d9 Mon Sep 17 00:00:00 2001 From: VitWW <130038091+VitWW@users.noreply.github.com> Date: Wed, 22 Jan 2025 00:37:24 +0200 Subject: [PATCH 5/5] more motivation --- text/0000-partial_types.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/0000-partial_types.md b/text/0000-partial_types.md index 5b140219b99..c1a9b06c0f1 100644 --- a/text/0000-partial_types.md +++ b/text/0000-partial_types.md @@ -15,6 +15,8 @@ Advantages: maximum type safety, maximum type control guarantee, no ambiguities, # Motivation [motivation]: #motivation +A lot of rust code where I need a struct mutable borrowed and stored paralelly to other borrows of the same struct but different fields. And partial borrowing is a good solution for these problems and they are highly needed. + Partial Types proposal is a generalization on "partial borrowing"-like proposals. Safe, Flexible controllable partial parameters for functions and partial consumption (including partial borrowing) are highly needed. Partial Types extension gives to Product Types (`PT = T1 and T2 and T3 and ..`), Structs and Tuples first of all, a good **mathematical guarantee** to borrow-checker that borrowing the whole variable with partial type and pretending to borrow just permitted fields is **fully safe** (without using `unsafe`). @@ -39,7 +41,7 @@ This extension is not only fully backward-compatible, but is fully forward-compa # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -Partiality of type (or partial type access) is written as `Path.{fld1, fld2, fld3}` after Path (Type name), where `fld1`, `fld2`, .. are only permitted to read (and maybe to write if variable is `mut`) fields of this type regardless of visibility, the rest of fields are forbidden to read and write and unset. +Partiality of type (or partial type access) is written as `Path.{fld1, fld2, fld3}` after Path (Type name), where `fld1`, `fld2`, .. are only permitted to read (and to write if variable is `mut`) fields of this type regardless of visibility, the rest of fields are forbidden to read and write and unset. Inverse partiality of type (or partial type access) is written as `Path.{off fld1, fld2, fld3}` after Path (Type name), where `off` is a new keyword and `fld1`, `fld2`, .. are only forbidden to read fields of this type regardless of visibility, the rest of fields are permitted to read (and maybe write) and unset.