You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Borrowck doesn't support partial borrow across regular function boundary.
View type aim to solve this problem.
With a classical approach where struct fields are private, Borrowck fail to reason about partial borrow across regular function boundary. If you start to write getters, you'll likely encounter a situation where you want to borrow disjoint fields of your struct across function call. You can't : a single getter lock the entiere memory region of the struct for Borrowck.
View type encapsulate another type and act as a readonly view. This is so far the cleanest and most ergonomic solution, as shown in the example below. As all fields are now public, Borrowck is able to figure out that we're actually borrowing disjoint fields.
The only inconvenience is that you need to define the ReadOnly structure in each module. This is because you want get_mut to only be accessible by the structure that owns ReadOnly (in other words, get_mut can't be public).
This pattern is already used in numerous code base.
#![allow(unused_variables)]#![allow(unused_mut)]#![allow(dead_code)]use std::ops::Deref;structReadOnly<T>{data:T,}impl<T>ReadOnly<T>{pubfnnew(data:T) -> Self{ReadOnly{ data }}pubfnget(&self) -> &T{&self.data}// Private.fnget_mut(&mutself) -> &mutT{&mutself.data}}impl<T>DerefforReadOnly<T>{typeTarget = T;fnderef(&self) -> &Self::Target{&self.data}}structFoo{puba:ReadOnly<Vec<i32>>,// Public read-only field.pubb:Vec<f32>,// Public read-write field.pubc:Vec<i32>,// Public read-write field.// ... maybe more fields ...pubz:Vec<bool>,// Public read-write field.}implFoo{pubfnnew() -> Self{Self{a:ReadOnly::new(vec![1, 2, 3]),b:vec![1.0, 2.0, 3.0],c:vec![-3, 0, 3],z:vec![false, true],}}}pubfnmain(){letmut foo = Foo::new();{// This now works.let x = foo.a.get();// Immutably borrow `a`.letmut y = &mut foo.b;// Mutably borrow `b`.for i in x {}// Immutably use `a`. }{// This is now erroneous.letmut x = &mut foo.a;// Can still borrow ReadOnly as mutable.letmut y = &mut foo.b;// Mutably borrow `b`.for i in x.iter_mut(){}// Can't use `a` as mutable.}}
C-additionCategory: Adding new content, something that didn't exist in the repository before
1 participant
Converted from issue
This discussion was converted from issue #343 on February 16, 2023 01:46.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Borrowck doesn't support partial borrow across regular function boundary.
View type aim to solve this problem.
With a classical approach where struct fields are private, Borrowck fail to reason about partial borrow across regular function boundary. If you start to write getters, you'll likely encounter a situation where you want to borrow disjoint fields of your struct across function call. You can't : a single getter lock the entiere memory region of the struct for Borrowck.
View type encapsulate another type and act as a readonly view. This is so far the cleanest and most ergonomic solution, as shown in the example below. As all fields are now public, Borrowck is able to figure out that we're actually borrowing disjoint fields.
The only inconvenience is that you need to define the ReadOnly structure in each module. This is because you want get_mut to only be accessible by the structure that owns ReadOnly (in other words, get_mut can't be public).
This pattern is already used in numerous code base.
Beta Was this translation helpful? Give feedback.
All reactions