I tried "translating" some sufficiently complex example:
struct S;
// used to better distinguish the use of `Option` in the translation
enum Maybe<T> {
Just(T),
#[allow(dead_code)]
Nothing,
}
use Maybe::*;
impl S {
fn test1(&self) -> bool {
false
}
fn test2(&self) -> bool {
true
}
fn consume(self) -> i32 {
1337
}
}
let x = Box::new(Just(Box::new(S)));
fn qux(_: &Box<S>) -> bool {
false
}
fn bar(_: &Box<Maybe<Box<S>>>) -> bool {
false
}
fn consume_box(_: Box<S>) -> i32 {
-1000000
}
/*
let _r = match x {
b if bar(&b) => {drop(b); 42}
deref Nothing => 123,
deref Just(s) if qux(&s) => consume_box(s),
b if bar(&b) => {drop(b); 420}
deref Just(deref S) if false => 0,
deref Just(deref s) if s.test1() => s.consume(),
b if bar(&b) => {drop(b); 4200}
deref Just(deref s) if s.test2() => s.consume(),
_ => 0,
}
*/
// translation in playground linked below
(See the actual translation here.)
using a DerefMove
trait. Bad Deref
implementations like the ones @CAD97 described can/will lead to panics in this translation. Also note how it is possible to avoid duplicating any calls to deref
.
I’m ignoring things like drop order here, so the translation might be not exactly what one would ultimately want here; also an actual compiler can probably use some thing like goto to avoid code duplication, so the trick using Option
like I did may be not necessary.