rust-lang / rust-lang/rust

Missed optimization: destructor of variable needlessly called before `unreachable_unchecked`

Open
#154,294 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-mir-opt C-optimization needs-triage T-compiler
Dominant language
Rust
Stars
119k
Forks
16.2k
PR merge metrics
PR metrics pending

Description

Here is a godbolt link demonstrating the issue: https://godbolt.org/z/3GvY6938x

Pasted here for posterity:

pub enum MyEnum {
  V1(u32),
  V2(u32),
  V3(String),
}

fn unsafe_cast_v1(v: MyEnum) -> u32 {
  match v {
    MyEnum::V1(v) => v,
    MyEnum::V2(v) => v,
    // The destructor of the string is called, even though `unreachable` immediately follows
    MyEnum::V3(_) => unsafe { std::hint::unreachable_unchecked() },
  }
}

fn unsafe_cast_v2(v: MyEnum) -> u32 {
  match v {
    MyEnum::V1(v) => v,
    MyEnum::V2(v) => v,
    // The destructor of the string is not called
    MyEnum::V3(_s) => unsafe { std::hint::unreachable_unchecked() },
  }
}

The only difference between these two code samples is that I have given the string associated data a name "_s" in the second example. My intuition tells me this causes its destructor to be called after the unreachable_unchecked, which is pruned because it is after !. The _ variable's destructor is called immediately, before calling unreachable_unchecked, so it is not pruned.

unreachable_unchecked is not just -> !, it can be assumed to never be reached. So we should be able to prune all code which happens unconditionally before it, not just after it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Rust code reproducer in the issue and inspect its generated output on the linked Godbolt example. Trace how the compiler handles the match arm containing unreachable_unchecked and the associated String destructor; done means the unnecessary destructor call is absent while the demonstrated behavior remains correct.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.