Skip to content

Warn on old editions when scrutinee is wrapped in a block #16827

@Darksonn

Description

@Darksonn

What it does

If the scrutinee of a match, if let, or while let statement is a block containing an expression without any statements, then warn unless the edition is 2024 or newer.

Advantage

As of the 2024 edition, wrapping the scrutinee in a block will ensure that temporaries created in the expression are dropped before the body executes. However, prior to the 2024 edition, this was not the case.

Drawbacks

None. If the block only contains a tail expression (no statements), then removing the block never changes behavior prior to the 2024 edition.

  • If the user meant to drop the temporaries, they have to change the code.
  • If the user did not mean to drop the temporaries, then removing the block makes the code less confusing without changing behavior.

Example

This code will deadlock:

if let Some(x) = self.inner.lock().unwrap().my_function() {
    self.inner.lock(); // <-- deadlocks on all editions
}

Someone might attempt to fix the above deadlock like this:

// OK on 2024 edition
// Should emit warning on 2021 edition.
if let Some(x) = { self.inner.lock().unwrap().my_function() } {
    self.inner.lock(); // <-- deadlocks on 2021 edition, but not on 2024 edition
}

However this fix only works due to a change to the lifetime of temporaries in the tail expression of blocks, so if the code is using the 2021 edition, then the fix does not work. The code must instead be written like this:

let value = self.inner.lock().unwrap().my_function();
if let Some(x) = value {
    self.inner.lock(); // <-- no deadlock
}

Comparison with existing lints

Although it's currently missing (see this bug: rust-lang/rust#155010), there is supposed to be an edition migration lint that would catch this. But I think we should have a version of this lint that is not an edition migration lint, as it catches real bugs and has no false positives.

Additional Context

This would have caught a real bug in the Rust Binder driver. See the fix here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintArea: New lints

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions