Open
Description
I am trying to learn what closure field capturing exactly does by studying the dumped MIR for a couple of interesting cases. Unfortunately that MIR contradicts itself:
fn call(f: impl FnOnce()) { f() }
#[derive(Default)]
struct S {
field0: u8,
field1: u8,
field2: u8,
}
fn test() {
let s = S::default();
call(|| {
let _v = &s.field1;
let _v = &s.field2;
})
}
prints this for the call site:
let _1: S;
bb1: {
_3 = &(_1.1: u8);
_4 = &(_1.2: u8);
_2 = [closure@src/lib.rs:12:10: 12:12] { s: move _3 };
_0 = call::<[closure@src/lib.rs:12:10: 12:12]>(move _2) -> [return: bb2, unwind continue];
}
and this for the closure body
fn test::{closure#0}(_1: [closure@src/lib.rs:12:10: 12:12]) -> () {
let mut _0: ();
let mut _2: &u8;
let mut _3: &u8;
bb0: {
_2 = deref_copy (_1.0: &u8);
_3 = deref_copy (_1.1: &u8);
return;
}
}
So at the call site it seems like the closure type has a single field called s
of type &u8
. But in the body it looks like it has 2 fields (MIR as usual only shows their indices, 0
and 1
) that each have type &u8
. Which one is true?
This test case prints "16" so it looks like there really are two reference-typed fields. That makes the printing at the site where the closure values are being captured rather misleading.