This reddit thread made me think about whether exposing the notion of unique borrowing (something which AFAIK the borrow checker already deals with) would add value to the core language. While I don’t agree with the OP of changing anything about owning types like Box<T>
, the concept of unique borrowing would be nice for user-defined types that are proxies trying to behave like a mutable reference, for example sync::MutexGuard
, cell::RefMut
or custom “mutable submatrix slice” one might want as part of a matrix computation library.
To those who don’t know what I mean by “unique borrowing”: Unique borrowing is like mutable borrowing in that it only allows one borrow at a time but does not require that thing being borrowed to be mutable. In cases where we have reference-like proxies, we don’t need to mutate these proxies in order to get mutable access, just uniqueness of the borrowing.
The observation is this:
let mut lock = somemutex.lock().unwrap();
// ^^^ is necessary for this to work:
lock.some_mutating_method();
Compare this to
let mut myint = 24;
let mymutref = &mut myint;
// ^ no mut here
*mymutref += 1;
We don’t need a mut
in the middle of let mymutref
and yet *mymutref
gives us mutable access. This is something that we can’t express in terms of function signagures. So, there is a disparity between mutable references and whatever custom data type you could come up with. Mutable references get special treatment. There is magic involved. Exposing unique borrowing in form of a reference type &uniq (or a similar mechanism) would allow the following
pub trait Deref { ... }
pub trait DerefMut: Deref { ... }
pub trait DerefUniq: DerefMut {
fn deref_uniq(&uniq self) -> &mut Self::Target
// ^^^^
}
Then, types like MutexGuard
which really try to behave like a mutable reference could implement DerefUniq
and make code like the following
let lock = somemutex.lock().unwrap();
lock.some_mutating_method();
work without making lock
mut
. It’s still safe because lock
is uniquely borrowed this way. This feels more like a mutable reference.
The question is: Is such a feature worth the hassle? Does it add enough value? Personally, I find the possibility to mimic mutable references with custom data types in this respect intriguing. What do you think?