Skip to content

lint against unexpectedly late drop for temporaries in match scrutinee expressions #93883

Open

Description

This came up recently on twitter: https://twitter.com/fasterthanlime/status/1491803585385877519

Where @fasterthanlime ran into an unexpected difference in behavior that caused a deadlock.

The following code works fine:

use parking_lot::Mutex;

struct State {}

impl State {
    fn foo(&self) -> bool {
        true
    }

    fn bar(&self) {}
}

fn main() {
    let mutex = Mutex::new(State {});

    let val = mutex.lock().foo();
    match val {
        true => {
            mutex.lock().bar();
        }
        false => {}
    };
    println!("All done!");
}

But when the mutex locking expression is inlined into the match scrutinee expression it causes deadlock:

    match mutex.lock().foo() {
        true => {
            mutex.lock().bar();
        }
        false => {}
    };

Link to playgrounds

This deadlock occurs because temporaries created in a match scrutinee automatically have their lifetime extended for the duration of the match expression. This is done to allow match arms to borrow from the scrutinee expressions, but this surprised many of the users in the above twitter thread because foo returns a bool, so there is no borrow taken by any of the match arms. My understanding is that the current behavior was chosen because otherwise drop timing of match temporaries would depend on whether or not you create any borrows.

This issue has generated some discussion around the possibility of changing drop rules in an edition to more aggressively drop temporaries. In this issue I would like to avoid a discussion of that size and instead propose that we introduce a lint that warns when one could encounter potentially surprising drop behaviour. @oli-obk has volunteered to mentor this issue. He suggested that we produce a warning when a temporary with a Drop impl which isn't borrowed by any match arms has its lifetime extended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

A-destructorsArea: Destructors (`Drop`, …)Area: Destructors (`Drop`, …)A-lintArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.C-feature-requestCategory: A feature request, i.e: not implemented / a PR.Category: A feature request, i.e: not implemented / a PR.E-help-wantedCall for participation: Help is requested to fix this issue.Call for participation: Help is requested to fix this issue.E-mediumCall for participation: Medium difficulty. Experience needed to fix: Intermediate.Call for participation: Medium difficulty. Experience needed to fix: Intermediate.E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions