I accidentally posted new updated proposal at "Reply" section, so I duplicate Updated Proposal here:
The simplest Partial Types:
All grammar:
- Partiality (A):
Partiality: DetailedPartiality | .%full | .%this
DetailedPartiality: .%{ PartialFields* }
PartialFields: PartialField (, PartialField )* ,?
PartialField: PermittedField Partiality?
PermittedField: IDENTIFIER | TUPLE_INDEX
- Expression partiality (A):
ExpressionWithoutBlock : OuterAttribute*† ( ... | FieldExpression | PartialExpression | ... )
PartialExpression: Expression Partiality
- Type partiality (A):
TupleType : ( ) | ( ( Type , )+ Type? ) Partiality?
TypePath : ::? TypePathSegment (:: TypePathSegment)* Partiality?
- Partial Mutability (B)
PartialMutability: mut Partiality?
- Expression Partial Mutability: (B)
BorrowExpression : (&|&&) Expression | (&|&&) PartialMutability? Expression
- Statement Partial Mutability: (B)
IdentifierPattern : ref? PartialMutability? IDENTIFIER (@ PatternNoTopAlt ) ?
Function:ShorthandSelf : (& | & Lifetime)? PartialMutability? self
Function:TypedSelf : PartialMutability? self : Type
- Typed Partial Mutability (B)
ReferenceType: & Lifetime? PartialMutability? TypeNoBounds
We could implement (A) before (B), but with (A without B) partial borrowing is not fully flexible.
We could change type of expression by PartialExpression
with next rule:
-
%deny
(not PermittedField) field always remains%deny
(no changes) -
%permit
(PermittedField) field could remain%permit
(no changes) -
%permit
(PermittedField) field could become%deny
(shrink type)
It is something like From
or as
cast, but PartialExpression
could change not full type, but just type partiality.
Example:
struct Point {x : i32, y : i32, z : i32, t : i32}
let var = Point{x:1, y:3, z:4, t:2};
// var : Point
// var : Point.%full
// var : Point.%{x,y,z,t}
let var_xyz = var.%{x,y,z};
// var_xyz : Point.%{x,y,z}
let var_xy = var_xyz.%{x,y};
// var : Point.%{x,y}
let var_x = var_xy.%{x};
// var_x : Point.%{x}
Borrowing rules for partial types:
-
%permit
(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. -
%deny
(not PermittedField) filed is always is ready to mutable and immutable borrow regardless if origin field is locked(by move, by reference, by borrow), is visible, is mutable.
For Partial Mutability
there is no special rules: it just indicates which fields are mutable and which are not.