Skip to content

Incorrect panic location when function is passed as argument #105942

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
scrabsha opened this issue Dec 20, 2022 · 3 comments
Open

Incorrect panic location when function is passed as argument #105942

scrabsha opened this issue Dec 20, 2022 · 3 comments
Labels
A-panic Area: Panicking machinery C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@scrabsha
Copy link
Contributor

Long story short: #[track_caller] leads to misleading span when a function is passed as argument.

I tried this code (playground link):

#[test]
fn panic_0() {
    Some(None::<()>).map(|o| o.unwrap());
}

#[test]
fn panic_1() {
    Some(None::<()>).map(Option::unwrap);
}

In this situation, both panic messages should be:

thread 'panic_X' panicked at 'called `Option::unwrap()` on a `None` value', src/lib.rs:LL:CC

However, panic_1 panics with the following message:

thread 'panic_1' panicked at 'called `Option::unwrap()` on a `None` value', /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:251:5

Permalink to function.rs:251:5

Ideally, the panic location should be spanned to src/lib.rs as well.

Meta

rustc --version --verbose:

rustc 1.64.0 (a55dd71d5 2022-09-19)
binary: rustc
commit-hash: a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52
commit-date: 2022-09-19
host: x86_64-unknown-linux-gnu
release: 1.64.0
LLVM version: 14.0.6

This happens on nightly as well.

Backtrace

panic_0 stacktrace:

thread 'panic_0' panicked at 'called `Option::unwrap()` on a `None` value', src/lib.rs:3:32
stack backtrace:
   0: rust_begin_unwind
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:575:5
   1: core::panicking::panic_fmt
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/panicking.rs:65:14
   2: core::panicking::panic
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/panicking.rs:115:5
   3: core::option::Option<T>::unwrap
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/option.rs:778:21
   4: playground::panic_0::{{closure}}
             at ./src/lib.rs:3:30
   5: core::option::Option<T>::map
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/option.rs:925:29
   6: playground::panic_0
             at ./src/lib.rs:3:5
   7: playground::panic_0::{{closure}}
             at ./src/lib.rs:2:1
   8: core::ops::function::FnOnce::call_once
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:251:5
   9: core::ops::function::FnOnce::call_once
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:251:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

panic_1 stacktrace:

thread 'panic_1' panicked at 'called `Option::unwrap()` on a `None` value', /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:251:5
stack backtrace:
   0: rust_begin_unwind
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:575:5
   1: core::panicking::panic_fmt
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/panicking.rs:65:14
   2: core::panicking::panic
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/panicking.rs:115:5
   3: core::option::Option<T>::unwrap
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/option.rs:778:21
   4: core::ops::function::FnOnce::call_once
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:251:5
   5: core::option::Option<T>::map
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/option.rs:925:29
   6: playground::panic_1
             at ./src/lib.rs:8:5
   7: playground::panic_1::{{closure}}
             at ./src/lib.rs:7:1
   8: core::ops::function::FnOnce::call_once
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:251:5
   9: core::ops::function::FnOnce::call_once
             at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:251:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

@scrabsha scrabsha added the C-bug Category: This is a bug. label Dec 20, 2022
@matthiaskrgr
Copy link
Member

Might be related to #105538

@nbdd0121
Copy link
Contributor

Might be related to #105538

I don't think this is MIR inlining related. If you have -Zinline-mir=no this outcome is not changed: https://godbolt.org/z/Me7er49s4.

I think the reason that function.rs is pointed to is that Option::map calls a generated shim (which then calls Option::unwrap instead) because Option::map calls FnOnce::call_once. And probably that generated shim is not #[track_caller] therefore the span of that shim is used.

@Enselic Enselic added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-panic Area: Panicking machinery and removed needs-triage-legacy labels Jul 13, 2024
@anchpop
Copy link

anchpop commented Apr 30, 2025

This came up again for me today. I made a post on reddit since I didn't know it was already a known issue: https://www.reddit.com/r/rust/comments/1kbm41y/track_caller_is_leaky_under_etaconversion/

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-panic Area: Panicking machinery C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants