Open
Description
When pattern bindings are lowered to MIR, they're dropped in reverse-order of declaration (with some caveats when or-patterns are involved). However, by-ref bindings are created eagerly before anything else if guards are present, so that they can be used in guards (#49870). Because that affects the order in which drops are scheduled, this difference is observable through the drop check (playground link):
struct Struct<T>(T);
impl<T> Drop for Struct<T> {
fn drop(&mut self) {}
}
fn main() {
// This is an error: `short1` is dead before `long1` is dropped.
match (Struct(&&0), 1) {
(mut long1, ref short1) => long1.0 = &short1,
}
// This is OK: `short2`'s storage is live until after `long2`'s drop runs.
match (Struct(&&0), 1) {
(mut long2, ref short2) if true => long2.0 = &short2,
_ => unreachable!(),
}
}
Related: #142056
cc @rust-lang/lang since if this needs fixing it'll involve changing what programs are allowed. I imagine that needs a T-lang decision?
@rustbot label: +T-compiler +T-lang +A-MIR
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
let
statements have anelse
block #142056Rollup merge of rust-lang#142193 - dianne:binding-drop-order-edge-cas…
Unrolled build for #142193
if let
guards (feature(if_let_guard)
) #141295traviscross commentedon Jun 13, 2025
Interesting finding. Thanks @dianne; we'll discuss in an upcoming call.
dianne commentedon Jun 18, 2025
One extra detail, in case it's relevant: this interacts with #142163 (test in-tree here):
traviscross commentedon Jun 19, 2025
We talked about this in lang triage. Thanks to both @dianne and @Nadrieril for joining us for that.
We agreed that this behavior is a bug, we're interested to see a PR proposing to fix that nominated for us, and we're curious to know what crater reports for that.