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