match lowering: consistently lower bindings deepest-first by Nadrieril · Pull Request #120214 · rust-lang/rust (original) (raw)

Currently when lowering match expressions to MIR, we do a funny little dance with the order of bindings. I attempt to explain it in the third commit: we handle refutable (i.e. needing a test) patterns differently than irrefutable ones. This leads to inconsistencies, as reported in #120210. The reason we need a dance at all is for situations like:

fn foo1(x: NonCopyStruct) { let y @ NonCopyStruct { copy_field: z } = x; // the above should turn into let z = x.copy_field; let y = x; }

Here the y @ binding will move out of x, so we need to copy the field first.

I believe that the inconsistency came about when we fixed #69971, and didn't notice that the fix didn't extend to refutable patterns. My guess then is that ordering bindings by "deepest-first, otherwise source order" is a sound choice. This PR implements that (at least I hope, match lowering is hard to follow 🥲).

Fixes #120210

r? @oli-obk since you merged the original fix to #69971
cc @matthewjasper