Skip to content

drop-checking is more permissive when patterns have guards #142057

Open
@dianne

Description

@dianne
Contributor

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

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
T-langRelevant to the language team
on Jun 5, 2025
removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Jun 8, 2025
added a commit that references this issue on Jun 9, 2025

Rollup merge of rust-lang#142193 - dianne:binding-drop-order-edge-cas…

9188dd7
added a commit that references this issue on Jun 9, 2025
added
I-lang-nominatedNominated for discussion during a lang team meeting.
P-lang-drag-1Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang
on Jun 13, 2025
traviscross

traviscross commented on Jun 13, 2025

@traviscross
Contributor

Interesting finding. Thanks @dianne; we'll discuss in an upcoming call.

dianne

dianne commented on Jun 18, 2025

@dianne
ContributorAuthor

One extra detail, in case it's relevant: this interacts with #142163 (test in-tree here):

// This depends on the binding modes of the final or-pattern alternatives (see #142163):
let res: &Result<u8, &u8> = &Ok(1);
match (Struct(&&0), res) {
    (mut long3, Ok(short3) | &Err(short3)) if true => long3.0 = &short3,
    //~^ ERROR `short3` does not live long enough
    _ => unreachable!(),
}
match (Struct(&&0), res) {
    (mut long4, &Err(short4) | Ok(short4)) if true => long4.0 = &short4,
    _ => unreachable!(),
}
traviscross

traviscross commented on Jun 19, 2025

@traviscross
Contributor

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.

removed
I-lang-nominatedNominated for discussion during a lang team meeting.
P-lang-drag-1Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang
on Jun 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @traviscross@dianne@rustbot@Noratrieb

        Issue actions

          drop-checking is more permissive when patterns have guards · Issue #142057 · rust-lang/rust