rust-lang / rust-lang/rust

matching on functions with similar call stacks breaks optimized backtraces even with debuginfo

Open
#134,909 13 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-backtrace A-debuginfo A-LLVM C-discussion T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code:

//@ compile-flags: -O -C debuginfo=full

fn main() {
    let x = String::from("unwrap_result");
    match &*x {
        "unwrap_result" => unwrap_result(),
        // Commenting out this line fixes the problem.
        "expect_result" => expect_result(),
        _ => {}
    }
}

// This function should appear in the backtrace.
fn unwrap_result() {
    Err(()).unwrap()
}

fn expect_result() {
    // Changing this line fixes the problem.
    Err(()).expect("oops");
}

I expected to see this happen:

stack backtrace:
   0: rust_begin_unwind
             at /rustc/14ee63a3c651bb7a243c8b07333749ab4b152e13/library/std/src/panicking.rs:676:5
   1: core::panicking::panic_fmt
             at /rustc/14ee63a3c651bb7a243c8b07333749ab4b152e13/library/core/src/panicking.rs:75:14
   2: core::result::unwrap_failed
             at /rustc/14ee63a3c651bb7a243c8b07333749ab4b152e13/library/core/src/result.rs:1704:5
   3: core::result::Result<T,E>::unwrap
             at /home/jyn/.local/lib/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:1109:23
   4: main::unwrap_result
             at ./src/main.rs:14:5
   5: main::main
             at ./src/main.rs:5:28
   6: core::ops::function::FnOnce::call_once
             at /home/jyn/.local/lib/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5

Instead, this happened:

stack backtrace:
   0: rust_begin_unwind
             at /rustc/14ee63a3c651bb7a243c8b07333749ab4b152e13/library/std/src/panicking.rs:676:5
   1: core::panicking::panic_fmt
             at /rustc/14ee63a3c651bb7a243c8b07333749ab4b152e13/library/core/src/panicking.rs:75:14
   2: core::result::unwrap_failed
             at /rustc/14ee63a3c651bb7a243c8b07333749ab4b152e13/library/core/src/result.rs:1704:5
   3: main::main
   4: core::ops::function::FnOnce::call_once
             at /home/jyn/.local/lib/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5

note how the line numbers have disappeared and the frames for unwrap_result and Result::unwrap have disappeared.

any of the following things fix the problem:

  • removing -O
  • commenting out the expect_result branch of the match
  • commenting out Err().expect() in the expect_result function. Note that this function is never called; changing it should not affect runtime behavior.
  • changing let x = String::from("unwrap_result") to let x = "unwrap_result". i suspect this lets llvm do constant folding or something like that?

note that i consider this a bug even though -O is present. the whole point of debuginfo is to work with inlined functions, and extremely similar programs that are optimized will have proper backtraces.

dwarfdump -i reports that there is no debuginfo at all present for unwrap_result; doing any of the 4 things above results in debuginfo being created. i verified with a local build of the compiler that this only affects the llvm backend, not cranelift.

Meta

rustc --version --verbose:

rustc 1.85.0-nightly (14ee63a3c 2024-12-29)
binary: rustc
commit-hash: 14ee63a3c651bb7a243c8b07333749ab4b152e13
commit-date: 2024-12-29
host: x86_64-unknown-linux-gnu
release: 1.85.0-nightly
LLVM version: 19.1.6

@rustbot label A-debuginfo A-backtrace A-llvm

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 by reproducing the optimized LLVM-backend case from the issue's src/main.rs example, then inspect the generated debuginfo with dwarfdump -i. Trace how optimized functions and inlined frames are represented, comparing the failing case with the listed changes that restore debuginfo. Done means the optimized backtrace retains unwrap_result and Result::unwrap with source locations.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.