Skip to content

Consuming a value with a destructuring pattern doesn't end its borrows for drop-check. #145032

@theemathas

Description

@theemathas

I tried this code:

struct Fork<'a>(&'a mut i32);

impl Drop for Fork<'_> {
    fn drop(&mut self) {}
}

fn parse(mut input: i32) {
    if let Some(fork) = Some(Fork(&mut input)) {
        drop(fork);
        let _x = input;
    }
}

I expected the code to compile, but I got the following error:

error[E0503]: cannot use `input` because it was mutably borrowed
  --> src/lib.rs:10:18
   |
 8 |     if let Some(fork) = Some(Fork(&mut input)) {
   |                         ----------------------
   |                         |         |
   |                         |         `input` is borrowed here
   |                         a temporary with access to the borrow is created here ...
 9 |         drop(fork);
10 |         let _x = input;
   |                  ^^^^^ use of borrowed `input`
11 |     };
   |     - ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Option<Fork<'_>>`

For more information about this error, try `rustc --explain E0503`.

I also tried using match instead of if let:

struct Fork<'a>(&'a mut i32);

impl Drop for Fork<'_> {
    fn drop(&mut self) {}
}

fn parse(mut input: i32) {
    match Some(Fork(&mut input)) {
        Some(fork) => {
            drop(fork);
            let _x = input;
        }
        _ => {}
    }
}

I got this error:

error[E0503]: cannot use `input` because it was mutably borrowed
  --> src/lib.rs:11:22
   |
 8 |     match Some(Fork(&mut input)) {
   |           ----------------------
   |           |         |
   |           |         `input` is borrowed here
   |           a temporary with access to the borrow is created here ...
...
11 |             let _x = input;
   |                      ^^^^^ use of borrowed `input`
...
14 |     }
   |     - ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Option<Fork<'_>>`
   |
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
   |
14 |     };
   |      +

For more information about this error, try `rustc --explain E0503`.

In either case, adding the semicolon, as indicated in the error, doesn't fix the error.

Minimized from real code by @spikespaz in the community discord.

Meta

Reproducible on the playground with version 1.91.0-nightly (2025-08-05 ec7c02612527d185c379)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-destructorsArea: Destructors (`Drop`, …)A-patternsRelating to patterns and pattern matchingC-bugCategory: This is a bug.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions