Skip to content

Proc-Macro-Diagnostics allow error subdiagnostics #145305

@stormofice

Description

@stormofice

Code

// Macro impl
#![feature(proc_macro_diagnostic)]

use proc_macro::{Diagnostic, Level, Span};

#[proc_macro_attribute]
pub fn proc_emit_err(
    _: proc_macro::TokenStream,
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    Diagnostic::new(Level::Error, "Parent message")
        .span_error(Span::call_site(), "Child message")
        .emit();

    input
}

// Application code 

#[proc_emit_err]
fn some_func() {}

Meta

rustc --version --verbose:

rustc 1.91.0-nightly (1ebbd87a6 2025-08-11)
binary: rustc
commit-hash: 1ebbd87a62ce96a72b22da61b7c2c43893534842
commit-date: 2025-08-11
host: x86_64-unknown-linux-gnu
release: 1.91.0-nightly
LLVM version: 21.1.0

Error output

error: custom attribute panicked
 --> poc/src/main.rs:3:1
  |
3 | #[proc_emit_err]
  | ^^^^^^^^^^^^^^^^
  |
  = help: message: assertion failed: child.level.can_be_subdiag()

error: could not compile `poc` (bin "poc") due to 1 previous error
Backtrace

thread 'rustc' panicked at compiler/rustc_errors/src/emitter.rs:2521:25:
assertion failed: child.level.can_be_subdiag()
stack backtrace:
   0:     0x7feb129caf85 - std::backtrace::Backtrace::create::h797e71eb0947b9a8
   1:     0x7feb129caed5 - std::backtrace::Backtrace::force_capture::h4488dd94f9a784fe
   2:     0x7feb11a25418 - std[675541678c9ea455]::panicking::update_hook::<alloc[69732d6495b06f7e]::boxed::Box<rustc_driver_impl[5f59bbdcc6d5c2ab]::install_ice_hook::{closure#1}>>::{closure#0}
   3:     0x7feb129e513e - std::panicking::panic_with_hook::h920938fbe8355f07
   4:     0x7feb129e4e06 - std::panicking::panic_handler::{{closure}}::hd7501236e9cac696
   5:     0x7feb129e1499 - std::sys::backtrace::__rust_end_short_backtrace::hd1de819b45b5e370
   6:     0x7feb129e4b1d - __rustc[d4effb916b19455c]::rust_begin_unwind
   7:     0x7feb0f0d1710 - core::panicking::panic_fmt::h7f4d53d811596956
   8:     0x7feb0f1692cc - core::panicking::panic::he98e298768f51c7f
   9:     0x7feb146e178e - <rustc_errors[92139785c6308770]::emitter::HumanEmitter as rustc_errors[92139785c6308770]::emitter::Emitter>::emit_diagnostic
  10:     0x7feb146e6559 - <rustc_errors[92139785c6308770]::json::Diagnostic>::from_errors_diagnostic
  11:     0x7feb146e5c60 - <rustc_errors[92139785c6308770]::json::JsonEmitter as rustc_errors[92139785c6308770]::emitter::Emitter>::emit_diagnostic
  12:     0x7feb146ef897 - <rustc_errors[92139785c6308770]::DiagCtxtInner>::emit_diagnostic::{closure#3}
  13:     0x7feb146ed014 - rustc_interface[fd75cb43796b9d5f]::callbacks::track_diagnostic::<core[f81d9d17b2423934]::option::Option<rustc_span[e8c7b9f398dc1a0]::ErrorGuaranteed>>
  14:     0x7feb146ec036 - <rustc_errors[92139785c6308770]::DiagCtxtInner>::emit_diagnostic
  15:     0x7feb146ebeff - <rustc_errors[92139785c6308770]::DiagCtxtHandle>::emit_diagnostic
  16:     0x7feb146ebd95 - <() as rustc_errors[92139785c6308770]::diagnostic::EmissionGuarantee>::emit_producing_guarantee
  17:     0x7feb11ad67a7 - <rustc_expand[9d5d7e814236ccf7]::proc_macro_server::Rustc as rustc_proc_macro[5300c59e89c06793]::bridge::server::FreeFunctions>::emit_diagnostic
  18:     0x7feb14187b33 - <rustc_proc_macro[5300c59e89c06793]::bridge::server::Dispatcher<rustc_proc_macro[5300c59e89c06793]::bridge::server::MarkedTypes<rustc_expand[9d5d7e814236ccf7]::proc_macro_server::Rustc>> as rustc_proc_macro[5300c59e89c06793]::bridge::server::DispatcherTrait>::dispatch
  19:     0x7feb14181cf0 - <rustc_proc_macro[5300c59e89c06793]::bridge::closure::Closure<_, _> as core[f81d9d17b2423934]::convert::From<&mut _>>::from::call::<rustc_proc_macro[5300c59e89c06793]::bridge::buffer::Buffer, rustc_proc_macro[5300c59e89c06793]::bridge::buffer::Buffer, <rustc_proc_macro[5300c59e89c06793]::bridge::server::SameThread as rustc_proc_macro[5300c59e89c06793]::bridge::server::ExecutionStrategy>::run_bridge_and_client<rustc_proc_macro[5300c59e89c06793]::bridge::server::Dispatcher<rustc_proc_macro[5300c59e89c06793]::bridge::server::MarkedTypes<rustc_expand[9d5d7e814236ccf7]::proc_macro_server::Rustc>>>::{closure#0}>
  20:     0x7feb01dbb242 - proc_macro::bridge::closure::Closure<A,R>::call::h9abe641c5d4c7980
                               at /rustc/1ebbd87a62ce96a72b22da61b7c2c43893534842/library/proc_macro/src/bridge/closure.rs:30:18
  21:     0x7feb01dbb242 - proc_macro::bridge::client::FreeFunctions::emit_diagnostic::{{closure}}::h8a4b9d0caf66a842
                               at /rustc/1ebbd87a62ce96a72b22da61b7c2c43893534842/library/proc_macro/src/bridge/client.rs:149:43
  22:     0x7feb01dbb242 - proc_macro::bridge::client::Bridge::with::{{closure}}::h12d48eda306488e9
                               at /rustc/1ebbd87a62ce96a72b22da61b7c2c43893534842/library/proc_macro/src/bridge/client.rs:227:13
  23:     0x7feb01dbb242 - proc_macro::bridge::client::state::with::h63edf330697cee2e
                               at /rustc/1ebbd87a62ce96a72b22da61b7c2c43893534842/library/proc_macro/src/bridge/client.rs:216:9
  24:     0x7feb01dbb242 - proc_macro::bridge::client::Bridge::with::h7fbff87cc01ce86c
                               at /rustc/1ebbd87a62ce96a72b22da61b7c2c43893534842/library/proc_macro/src/bridge/client.rs:222:9
  25:     0x7feb01dbb242 - proc_macro::bridge::client::FreeFunctions::emit_diagnostic::hc42ef8d6f72ea9a4
                               at /rustc/1ebbd87a62ce96a72b22da61b7c2c43893534842/library/proc_macro/src/bridge/client.rs:142:17
  26:     0x7feb01dbb242 - proc_macro::diagnostic::Diagnostic::emit::ha8d39ee2381b2405
                               at /rustc/1ebbd87a62ce96a72b22da61b7c2c43893534842/library/proc_macro/src/diagnostic.rs:173:9
  27:     0x7feb01db8bdf - proc_repro::proc_emit_err::hde8a2cd045407e13
                               at ~/proc-macro-diagnostic/proc_repro/src/lib.rs:13:10
  28:     0x7feb01db585e - core::ops::function::Fn::call::h2b91dd43179b7a1f
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:80:5
  29:     0x7feb01db6ead - proc_macro::bridge::client::Client<(proc_macro::TokenStream,proc_macro::TokenStream),proc_macro::TokenStream>::expand2::{{closure}}::{{closure}}::h4f3ce69c7940cd67
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/proc_macro/src/bridge/client.rs:351:21
  30:     0x7feb01db6e52 - proc_macro::bridge::client::run_client::{{closure}}::{{closure}}::h675371de5293ecd3
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/proc_macro/src/bridge/client.rs:302:44
  31:     0x7feb01db950e - proc_macro::bridge::client::state::set::h06602bf8e8fb3182
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/proc_macro/src/bridge/client.rs:201:9
  32:     0x7feb01db6c66 - proc_macro::bridge::client::run_client::{{closure}}::h6bb7c7332db97092
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/proc_macro/src/bridge/client.rs:302:22
  33:     0x7feb01db7470 - <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::h2f102f5494eb2abf
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:272:9
  34:     0x7feb01db706b - std::panicking::catch_unwind::do_call::h3c79b37c9aed3507
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:590:40
  35:     0x7feb01db6f6b - __rust_try
  36:     0x7feb01db67db - std::panicking::catch_unwind::h4f4f83267e3b7eb1
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:553:19
  37:     0x7feb01db67db - std::panic::catch_unwind::h9dd35db126f39070
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:357:14
  38:     0x7feb01db67db - proc_macro::bridge::client::run_client::hbb8fa7e37ab22308
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/proc_macro/src/bridge/client.rs:290:5
  39:     0x7feb01db6e81 - proc_macro::bridge::client::Client<(proc_macro::TokenStream,proc_macro::TokenStream),proc_macro::TokenStream>::expand2::{{closure}}::h6017f2c767b896f3
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/proc_macro/src/bridge/client.rs:350:17
  40:     0x7feb01db9724 - proc_macro::bridge::selfless_reify::reify_to_extern_c_fn_hrt_bridge::wrapper::h0bec6f105583baae
                               at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/proc_macro/src/bridge/selfless_reify.rs:64:17
  41:     0x7feb13f4a3c1 - <rustc_proc_macro[5300c59e89c06793]::bridge::server::MaybeCrossThread<rustc_expand[9d5d7e814236ccf7]::proc_macro::MessagePipe<rustc_proc_macro[5300c59e89c06793]::bridge::buffer::Buffer>> as rustc_proc_macro[5300c59e89c06793]::bridge::server::ExecutionStrategy>::run_bridge_and_client::<rustc_proc_macro[5300c59e89c06793]::bridge::server::Dispatcher<rustc_proc_macro[5300c59e89c06793]::bridge::server::MarkedTypes<rustc_expand[9d5d7e814236ccf7]::proc_macro_server::Rustc>>>
  42:     0x7feb13f499b0 - <rustc_expand[9d5d7e814236ccf7]::proc_macro::AttrProcMacro as rustc_expand[9d5d7e814236ccf7]::base::AttrProcMacro>::expand
  43:     0x7feb147a864f - <rustc_expand[9d5d7e814236ccf7]::expand::MacroExpander>::fully_expand_fragment
  44:     0x7feb14788be9 - <rustc_expand[9d5d7e814236ccf7]::expand::MacroExpander>::expand_crate
  45:     0x7feb13d5b328 - rustc_interface[fd75cb43796b9d5f]::passes::configure_and_expand
  46:     0x7feb143b76ed - rustc_interface[fd75cb43796b9d5f]::passes::resolver_for_lowering_raw
  47:     0x7feb143b744d - rustc_query_impl[52ced257674aa24b]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[52ced257674aa24b]::query_impl::resolver_for_lowering_raw::dynamic_query::{closure#2}::{closure#0}, rustc_middle[c7deae55f4bd1b39]::query::erase::Erased<[u8; 16usize]>>
  48:     0x7feb143b7427 - <rustc_query_impl[52ced257674aa24b]::query_impl::resolver_for_lowering_raw::dynamic_query::{closure#2} as core[f81d9d17b2423934]::ops::function::FnOnce<(rustc_middle[c7deae55f4bd1b39]::ty::context::TyCtxt, ())>>::call_once
  49:     0x7feb1461f8f1 - rustc_query_system[8d730556a4fd7a7]::query::plumbing::try_execute_query::<rustc_query_impl[52ced257674aa24b]::DynamicConfig<rustc_query_system[8d730556a4fd7a7]::query::caches::SingleCache<rustc_middle[c7deae55f4bd1b39]::query::erase::Erased<[u8; 16usize]>>, false, false, false>, rustc_query_impl[52ced257674aa24b]::plumbing::QueryCtxt, true>
  50:     0x7feb1461f301 - rustc_query_impl[52ced257674aa24b]::query_impl::resolver_for_lowering_raw::get_query_incr::__rust_end_short_backtrace
  51:     0x7feb143e8636 - rustc_interface[fd75cb43796b9d5f]::passes::create_and_enter_global_ctxt::<core[f81d9d17b2423934]::option::Option<rustc_interface[fd75cb43796b9d5f]::queries::Linker>, rustc_driver_impl[5f59bbdcc6d5c2ab]::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}
  52:     0x7feb144e60e1 - rustc_interface[fd75cb43796b9d5f]::interface::run_compiler::<(), rustc_driver_impl[5f59bbdcc6d5c2ab]::run_compiler::{closure#0}>::{closure#1}
  53:     0x7feb1433cd87 - std[675541678c9ea455]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[fd75cb43796b9d5f]::util::run_in_thread_with_globals<rustc_interface[fd75cb43796b9d5f]::util::run_in_thread_pool_with_globals<rustc_interface[fd75cb43796b9d5f]::interface::run_compiler<(), rustc_driver_impl[5f59bbdcc6d5c2ab]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
  54:     0x7feb1433ca68 - <<std[675541678c9ea455]::thread::Builder>::spawn_unchecked_<rustc_interface[fd75cb43796b9d5f]::util::run_in_thread_with_globals<rustc_interface[fd75cb43796b9d5f]::util::run_in_thread_pool_with_globals<rustc_interface[fd75cb43796b9d5f]::interface::run_compiler<(), rustc_driver_impl[5f59bbdcc6d5c2ab]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core[f81d9d17b2423934]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  55:     0x7feb1434230b - std::sys::pal::unix::thread::Thread::new::thread_start::had526f783dce54b0
  56:     0x7feb0da969cb - <unknown>
  57:     0x7feb0db1aa4c - <unknown>
  58:                0x0 - <unknown>


rustc version: 1.91.0-nightly (1ebbd87a6 2025-08-11)
platform: x86_64-unknown-linux-gnu

query stack during panic:
#0 [resolver_for_lowering_raw] getting the resolver for lowering
end of query stack


Diagnostic functions for generating error subdiags are generated here:

diagnostic_child_methods!(span_error, error, Level::Error);

can_be_subdiag disallows Error Level:

fn can_be_subdiag(&self) -> bool {

Finally, breaks assertion when emitting:

assert!(child.level.can_be_subdiag());

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-proc-macrosArea: Procedural macrosC-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions