Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Macro runtime error not helpful 🐛 #114055

Open
0nyr opened this issue Jul 25, 2023 · 2 comments
Open

Macro runtime error not helpful 🐛 #114055

0nyr opened this issue Jul 25, 2023 · 2 comments
Assignees
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@0nyr
Copy link

0nyr commented Jul 25, 2023

Code

// Here is a basic example of macro that has a runtime error. 

macro_rules! runtime_error_macro {
    () => {
        let test: Option<i32> = None;
        test.unwrap();
    };
}

fn main() {
    runtime_error_macro!();
}

Current output

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:9:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

# with RUST_BACKTRACE=1:
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:9:5
stack backtrace:
   0: rust_begin_unwind
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/std/src/panicking.rs:617:5
   1: core::panicking::panic_fmt
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/core/src/panicking.rs:67:14
   2: core::panicking::panic
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/core/src/panicking.rs:117:5
   3: core::option::Option<T>::unwrap
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/core/src/option.rs:935:21
   4: rust_macro_error_example::main
             at ./src/main.rs:9:5
   5: core::ops::function::FnOnce::call_once
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/core/src/ops/function.rs:250:5

Desired output

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:9:5
in macro test_failing_macro, src/main.rs:4:12
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

# with RUST_BACKTRACE=1:
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:9:5
stack backtrace:
   0: rust_begin_unwind
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/std/src/panicking.rs:617:5
   1: core::panicking::panic_fmt
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/core/src/panicking.rs:67:14
   2: core::panicking::panic
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/core/src/panicking.rs:117:5
   3: core::option::Option<T>::unwrap
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/core/src/option.rs:935:21
   4': rust_macro_error_example::main
             at src/main.rs:4:12
   4: rust_macro_error_example::main
             at ./src/main.rs:9:5
   5: core::ops::function::FnOnce::call_once
             at /rustc/31395ec38250b60b380fd3c27e94756aba3557de/library/core/src/ops/function.rs:250:5

Rationale and extra context

Working with macro, and especially debugging macro code is challenging in Rust. Contrary to all the helpful Rust compile and runtime errors we are used to for non-macro code, error line is not given if any runtime error occurs inside a macro expansion. This quickly becomes challenging, with macros within macros.

It seems like related Issues are also related to this issue, like #100235.

In a related closed discussion about improving compile-time macro errors it is recalled that there are actually 2 users of macros: people that develop them, and people that use them.

In the context of runtime error, it seems logical to give both the line invocation of the macro, as well as the line inside the macro expansion that gives the error, so that both macro users can better report bugs and errors, and developers can easily correct the problem. This information should at least be present in the backtrack of the error (while using RUST_BACKTRACE=1).

Currently, there isn't an automatic way to have Rust provide line numbers within the expanded macros when you encounter a runtime error. Since macro expansion is a compile-time operation, and it abstracts away the internals of the macro from the runtime system, it's seems hard to develop such a system. It's only possible to expand macros using a nightly compile flag of rustc called -Zunpretty=expanded, but it's very insufficient, as it just prints a new expanded flag, with no automatic compile or run, making debugging of runtime errors in macro challenging. The proposed improvement would really improve greatly this process, as well a bug reporting.

Other cases

Although the runtime error gives the macro invocation line, as well as the code error origin, here 'Option::unwrap()' on a 'None' value", this is not really helpful. In a real project scenario, with dozens of unwrap and nested macros, it's quite challenging to rely only on the knowledge that the error is occurring on an unwrap. I took the example of unwrap but it's the same for any runtime error inside a macro.

Below is a slightly more complex example:

macro_rules! runtime_error_macro {
    () => {
        let test: Option<i32> = None;
        test.unwrap();
    };
}

macro_rules! runtime_error_macro_nested {
    () => {
        let test1: Option<i32> = None;
        test1.unwrap();

        let test2: Option<i32> = Some(42);
        test2.unwrap();

        runtime_error_macro!();
    };
}

fn main() {
    println!("Hello, world!");

    runtime_error_macro_nested!();
}

Compiling and running with either cargo run or rustc src/main.rs -o main, ./main gives:

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:23:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

In this situation, it's easy to understand that having more information of the line of the error from within the error invocation, or information about the context, like lines before and after, would be very previous to understand where the error is actually coming from.

Anything else?

This issue has been created by fitz35 and me.

@0nyr 0nyr added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 25, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jul 25, 2023
@saethlin saethlin removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jul 25, 2023
@estebank estebank added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) and removed A-diagnostics Area: Messages for errors, warnings, and lints labels Jul 28, 2023
@estebank
Copy link
Contributor

CC
#41743
#39153 (comment)
#89920

@vincenzopalazzo
Copy link
Member

@rustbot claim

As discussed in the today triage meeting today, I would like to look at the history for this and maybe propose a working plan to include inside the wg vision for macros

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) 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

5 participants