Skip to content

pin!() has incorrect/unexpected drop order inside if-let. #145328

@theemathas

Description

@theemathas

My intuition is that, with regards to drop order, pin!(expr) should behave like &mut expr. However, this is not the case inside let chains.

use std::pin::pin;

struct LoudDrop(&'static str);
impl Drop for LoudDrop {
    fn drop(&mut self) {
        println!("{}", self.0);
    }
}

fn main() {
    if let x = LoudDrop("0")
        && let y = pin!(LoudDrop("1"))
    {}
    if let x = LoudDrop("3")
        && let y = &mut LoudDrop("2")
    {}
}

The above code outputs: 0, 1, 2, 3. It should output 1, 0, 2, 3.

cc @m-ou-se

Discovered in #141295 (comment)

Note that pin!() started being implemented with super let in version 1.88.0, the same version where let chains were stabilized.

@rustbot labels +A-pin +F-let_chains +A-destructors +F-super_let

Meta

Reproducible on the playground with version 1.89.0 and version 1.91.0-nightly (2025-08-11 1ebbd87a62ce96a72b22)

Metadata

Metadata

Assignees

Labels

A-destructorsArea: Destructors (`Drop`, …)A-pinArea: PinC-bugCategory: This is a bug.F-let_chains`#![feature(let_chains)]`F-super_letit's super, let's go!I-libs-api-nominatedNominated for discussion during a libs-api team meeting.P-criticalCritical priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamregression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions