Place Aliases
This feature adds place p bindings, allowed anywhere patterns are except inside or-patterns.
let place p = $expr; evaluates $expr to a place expression and then works as an alias to that
place.
It expresses the idea of "compute a place once and use it many times". In practice, if we apply our
initial desugaring steps to let place p = $expr;, we end up with $expr being a side-effect-free
place expression, which we can then syntactically substitute wherever p is used
(this is done in the Desugaring Bindings step).
For example:
#![allow(unused)] fn main() { let place p = x.field; // this does not try to move out of the place something(&p); something_else(p); // now this moves out // would be desugared to: something(&x.field); something_else(x.field); // now this moves out }
#![allow(unused)] fn main() { let place p = x.method().field; something(&p); // would be desugared to: let tmp = x.method(); something(&tmp.field); }
The one point where this feature is a bit tricky is autoderef:
#![allow(unused)] fn main() { let mut x: std::cell::RefMut<Struct> = ...; let place p = x.field; // should this use `deref` or `deref_mut`? something(&p); something_else(&mut p); // causes `deref_mut` to be called above // becomes: let mut x: std::cell::RefMut<Struct> = ...; let tmp = <_ as DerefMut>::deref_mut(&mut x) let place p = (*tmp).field; something(&p); something_else(&mut p); // and then: let mut x: std::cell::RefMut<Struct> = ...; let mut x: std::cell::RefMut<Struct> = ...; let tmp = <_ as DerefMut>::deref_mut(&mut x) something(&(*tmp).field); something_else(&mut (*tmp).field); }
For that to work, when determining the mutability that a place p binding requires of its matched
place, we consider the mutability required of p anywhere it is used.
This is done in the Deref/DerefMut Desugarings step.
Conditional Place Aliases
This is bit of a crazy feature extension, added to avoid duplicating code in Let Chain Desugaring.
This introduces a built-in macro if_place!($bool, $place1, $place2), valid as a place expression, which
behaves as follows:
- It propagates any place operation to the inside:
if_place!($bool, $place1, $place2).field = if_place!($bool, $place1.field, $place2.field); - When a non-place operation is done to it, it turns into a normal
if:&if_place!($bool, $place1, $place2) = if $bool { &$place1 } else { &$place2 }.
This is the only feature among those proposed that I don't actually wish to see in the language. I hope we can find a cleaner solution to the code duplication problem.
Backlinks