Skip to content

Commit 78ee1bc

Browse files
committed
debuginfo: Stabilize -Z debug-macros, -Z collapse-macro-debuginfo and #[collapse_debuginfo]
`-Z debug-macros` is "stabilized" by enabling it by default and removing. `-Z collapse-macro-debuginfo` is stabilized as `-C collapse-macro-debuginfo`. It now supports all typical boolean values (`parse_opt_bool`) in addition to just yes/no. Default value of `collapse_debuginfo` was changed from `false` to `external` (i.e. collapsed if external, not collapsed if local). `#[collapse_debuginfo]` attribute without a value is no longer supported to avoid guessing the default.
1 parent 8fb67fb commit 78ee1bc

27 files changed

+192
-337
lines changed

compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use gimli::write::{
1010
};
1111
use rustc_data_structures::sync::Lrc;
1212
use rustc_span::{
13-
FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
13+
hygiene, FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
1414
};
1515

1616
use crate::debuginfo::FunctionDebugContext;
@@ -64,11 +64,8 @@ impl DebugContext {
6464
function_span: Span,
6565
span: Span,
6666
) -> (Lrc<SourceFile>, u64, u64) {
67-
// Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
68-
// In order to have a good line stepping behavior in debugger, we overwrite debug
69-
// locations of macro expansions with that of the outermost expansion site (when the macro is
70-
// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
71-
let span = tcx.collapsed_debuginfo(span, function_span);
67+
// Match behavior of `FunctionCx::adjusted_span_and_dbg_scope`.
68+
let span = hygiene::walk_chain_collapsed(span, function_span);
7269
match tcx.sess.source_map().lookup_line(span.lo()) {
7370
Ok(SourceFileAndLine { sf: file, line }) => {
7471
let line_pos = file.lines()[line];

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

+3-19
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ use rustc_index::IndexVec;
44
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
55
use rustc_middle::mir;
66
use rustc_middle::ty;
7-
use rustc_middle::ty::layout::TyAndLayout;
8-
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
7+
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
98
use rustc_middle::ty::Instance;
109
use rustc_middle::ty::Ty;
1110
use rustc_session::config::DebugInfo;
1211
use rustc_span::symbol::{kw, Symbol};
13-
use rustc_span::{BytePos, Span};
12+
use rustc_span::{hygiene, BytePos, Span};
1413
use rustc_target::abi::{Abi, FieldIdx, FieldsShape, Size, VariantIdx};
1514

1615
use super::operand::{OperandRef, OperandValue};
@@ -220,26 +219,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
220219
&self,
221220
source_info: mir::SourceInfo,
222221
) -> Option<(Bx::DIScope, Option<Bx::DILocation>, Span)> {
223-
let span = self.adjust_span_for_debugging(source_info.span);
224222
let scope = &self.debug_context.as_ref()?.scopes[source_info.scope];
223+
let span = hygiene::walk_chain_collapsed(source_info.span, self.mir.span);
225224
Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span))
226225
}
227226

228-
/// In order to have a good line stepping behavior in debugger, we overwrite debug
229-
/// locations of macro expansions with that of the outermost expansion site (when the macro is
230-
/// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
231-
fn adjust_span_for_debugging(&self, span: Span) -> Span {
232-
// Bail out if debug info emission is not enabled.
233-
if self.debug_context.is_none() {
234-
return span;
235-
}
236-
// Walk up the macro expansion chain until we reach a non-expanded span.
237-
// We also stop at the function body level because no line stepping can occur
238-
// at the level above that.
239-
// Use span of the outermost expansion site, while keeping the original lexical scope.
240-
self.cx.tcx().collapsed_debuginfo(span, self.mir.span)
241-
}
242-
243227
fn spill_operand_to_stack(
244228
operand: OperandRef<'tcx, Bx::Value>,
245229
name: Option<String>,

compiler/rustc_expand/src/base.rs

+35-40
Original file line numberDiff line numberDiff line change
@@ -763,55 +763,50 @@ impl SyntaxExtension {
763763
}
764764
}
765765

766-
fn collapse_debuginfo_by_name(sess: &Session, attr: &Attribute) -> CollapseMacroDebuginfo {
767-
use crate::errors::CollapseMacroDebuginfoIllegal;
768-
// #[collapse_debuginfo] without enum value (#[collapse_debuginfo(no/external/yes)])
769-
// considered as `yes`
770-
attr.meta_item_list().map_or(CollapseMacroDebuginfo::Yes, |l| {
771-
let [NestedMetaItem::MetaItem(item)] = &l[..] else {
772-
sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: attr.span });
773-
return CollapseMacroDebuginfo::Unspecified;
774-
};
775-
if !item.is_word() {
776-
sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span });
777-
CollapseMacroDebuginfo::Unspecified
778-
} else {
779-
match item.name_or_empty() {
780-
sym::no => CollapseMacroDebuginfo::No,
781-
sym::external => CollapseMacroDebuginfo::External,
782-
sym::yes => CollapseMacroDebuginfo::Yes,
783-
_ => {
784-
sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span });
785-
CollapseMacroDebuginfo::Unspecified
786-
}
787-
}
788-
}
789-
})
766+
fn collapse_debuginfo_by_name(attr: &Attribute) -> Result<CollapseMacroDebuginfo, Span> {
767+
let list = attr.meta_item_list();
768+
let Some([NestedMetaItem::MetaItem(item)]) = list.as_deref() else {
769+
return Err(attr.span);
770+
};
771+
if !item.is_word() {
772+
return Err(item.span);
773+
}
774+
775+
match item.name_or_empty() {
776+
sym::no => Ok(CollapseMacroDebuginfo::No),
777+
sym::external => Ok(CollapseMacroDebuginfo::External),
778+
sym::yes => Ok(CollapseMacroDebuginfo::Yes),
779+
_ => Err(item.path.span),
780+
}
790781
}
791782

792783
/// if-ext - if macro from different crate (related to callsite code)
793784
/// | cmd \ attr | no | (unspecified) | external | yes |
794785
/// | no | no | no | no | no |
795-
/// | (unspecified) | no | no | if-ext | yes |
786+
/// | (unspecified) | no | if-ext | if-ext | yes |
796787
/// | external | no | if-ext | if-ext | yes |
797788
/// | yes | yes | yes | yes | yes |
798-
fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool {
799-
let mut collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
800-
.map(|v| Self::collapse_debuginfo_by_name(sess, v))
801-
.unwrap_or(CollapseMacroDebuginfo::Unspecified);
802-
if collapse_debuginfo_attr == CollapseMacroDebuginfo::Unspecified
803-
&& attr::contains_name(attrs, sym::rustc_builtin_macro)
804-
{
805-
collapse_debuginfo_attr = CollapseMacroDebuginfo::Yes;
806-
}
807-
808-
let flag = sess.opts.unstable_opts.collapse_macro_debuginfo;
809-
let attr = collapse_debuginfo_attr;
810-
let ext = !is_local;
789+
fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], ext: bool) -> bool {
790+
let flag = sess.opts.cg.collapse_macro_debuginfo;
791+
let attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
792+
.and_then(|attr| {
793+
Self::collapse_debuginfo_by_name(attr)
794+
.map_err(|span| {
795+
sess.dcx().emit_err(errors::CollapseMacroDebuginfoIllegal { span })
796+
})
797+
.ok()
798+
})
799+
.unwrap_or_else(|| {
800+
if attr::contains_name(attrs, sym::rustc_builtin_macro) {
801+
CollapseMacroDebuginfo::Yes
802+
} else {
803+
CollapseMacroDebuginfo::Unspecified
804+
}
805+
});
811806
#[rustfmt::skip]
812807
let collapse_table = [
813808
[false, false, false, false],
814-
[false, false, ext, true],
809+
[false, ext, ext, true],
815810
[false, ext, ext, true],
816811
[true, true, true, true],
817812
];
@@ -838,7 +833,7 @@ impl SyntaxExtension {
838833
let local_inner_macros = attr::find_by_name(attrs, sym::macro_export)
839834
.and_then(|macro_export| macro_export.meta_item_list())
840835
.is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros));
841-
let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, is_local);
836+
let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local);
842837
tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
843838

844839
let (builtin_name, helper_attrs) = attr::find_by_name(attrs, sym::rustc_builtin_macro)

compiler/rustc_feature/src/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ declare_features! (
9494
(accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
9595
/// Allows using the CMPXCHG16B target feature.
9696
(accepted, cmpxchg16b_target_feature, "1.69.0", Some(44839)),
97+
/// Allows use of the `#[collapse_debuginfo]` attribute.
98+
(accepted, collapse_debuginfo, "CURRENT_RUSTC_VERSION", Some(100758)),
9799
/// Allows usage of the `compile_error!` macro.
98100
(accepted, compile_error, "1.20.0", Some(40872)),
99101
/// Allows `impl Trait` in function return types.

compiler/rustc_feature/src/builtin_attrs.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
408408
debugger_visualizer, Normal,
409409
template!(List: r#"natvis_file = "...", gdb_script_file = "...""#), DuplicatesOk
410410
),
411+
ungated!(collapse_debuginfo, Normal, template!(List: "no|external|yes"), ErrorFollowing),
411412

412413
// ==========================================================================
413414
// Unstable attributes:
@@ -464,12 +465,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
464465
experimental!(deprecated_safe),
465466
),
466467

467-
// `#[collapse_debuginfo]`
468-
gated!(
469-
collapse_debuginfo, Normal, template!(Word, List: "no|external|yes"), ErrorFollowing,
470-
experimental!(collapse_debuginfo)
471-
),
472-
473468
// RFC 2397
474469
gated!(do_not_recommend, Normal, template!(Word), WarnFollowing, experimental!(do_not_recommend)),
475470

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,6 @@ declare_features! (
391391
(unstable, closure_track_caller, "1.57.0", Some(87417)),
392392
/// Allows to use the `#[cmse_nonsecure_entry]` attribute.
393393
(unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)),
394-
/// Allows use of the `#[collapse_debuginfo]` attribute.
395-
(unstable, collapse_debuginfo, "1.65.0", Some(100758)),
396394
/// Allows `async {}` expressions in const contexts.
397395
(unstable, const_async_blocks, "1.53.0", Some(85368)),
398396
/// Allows `const || {}` closures in const contexts.

compiler/rustc_interface/src/tests.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ fn test_codegen_options_tracking_hash() {
583583
// Make sure that changing a [TRACKED] option changes the hash.
584584
// tidy-alphabetical-start
585585
tracked!(code_model, Some(CodeModel::Large));
586+
tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes);
586587
tracked!(control_flow_guard, CFGuard::Checks);
587588
tracked!(debug_assertions, Some(true));
588589
tracked!(debuginfo, DebugInfo::Limited);
@@ -742,11 +743,9 @@ fn test_unstable_options_tracking_hash() {
742743
})
743744
);
744745
tracked!(codegen_backend, Some("abc".to_string()));
745-
tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes);
746746
tracked!(crate_attr, vec!["abc".to_string()]);
747747
tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
748748
tracked!(debug_info_for_profiling, true);
749-
tracked!(debug_macros, true);
750749
tracked!(default_hidden_visibility, Some(true));
751750
tracked!(dep_info_omit_d_target, true);
752751
tracked!(direct_access_external_data, Some(true));

compiler/rustc_middle/src/ty/mod.rs

+1-17
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use rustc_session::lint::LintBuffer;
5151
pub use rustc_session::lint::RegisteredTools;
5252
use rustc_span::hygiene::MacroKind;
5353
use rustc_span::symbol::{kw, sym, Ident, Symbol};
54-
use rustc_span::{hygiene, ExpnId, ExpnKind, Span};
54+
use rustc_span::{ExpnId, ExpnKind, Span};
5555
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
5656
pub use rustc_target::abi::{ReprFlags, ReprOptions};
5757
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
@@ -1867,22 +1867,6 @@ impl<'tcx> TyCtxt<'tcx> {
18671867
(ident, scope)
18681868
}
18691869

1870-
/// Returns corrected span if the debuginfo for `span` should be collapsed to the outermost
1871-
/// expansion site (with collapse_debuginfo attribute if the corresponding feature enabled).
1872-
/// Only applies when `Span` is the result of macro expansion.
1873-
///
1874-
/// - If the `collapse_debuginfo` feature is enabled then debuginfo is not collapsed by default
1875-
/// and only when a (some enclosing) macro definition is annotated with `#[collapse_debuginfo]`.
1876-
/// - If `collapse_debuginfo` is not enabled, then debuginfo is collapsed by default.
1877-
///
1878-
/// When `-Zdebug-macros` is provided then debuginfo will never be collapsed.
1879-
pub fn collapsed_debuginfo(self, span: Span, upto: Span) -> Span {
1880-
if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() {
1881-
return span;
1882-
}
1883-
hygiene::walk_chain_collapsed(span, upto, self.features().collapse_debuginfo)
1884-
}
1885-
18861870
#[inline]
18871871
pub fn is_const_fn_raw(self, def_id: DefId) -> bool {
18881872
matches!(

compiler/rustc_session/src/options.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -1309,10 +1309,20 @@ mod parse {
13091309
slot: &mut CollapseMacroDebuginfo,
13101310
v: Option<&str>,
13111311
) -> bool {
1312+
if v.is_some() {
1313+
let mut bool_arg = None;
1314+
if parse_opt_bool(&mut bool_arg, v) {
1315+
*slot = if bool_arg.unwrap() {
1316+
CollapseMacroDebuginfo::Yes
1317+
} else {
1318+
CollapseMacroDebuginfo::No
1319+
};
1320+
return true;
1321+
}
1322+
}
1323+
13121324
*slot = match v {
1313-
Some("no") => CollapseMacroDebuginfo::No,
13141325
Some("external") => CollapseMacroDebuginfo::External,
1315-
Some("yes") => CollapseMacroDebuginfo::Yes,
13161326
_ => return false,
13171327
};
13181328
true
@@ -1402,6 +1412,9 @@ options! {
14021412
"choose the code model to use (`rustc --print code-models` for details)"),
14031413
codegen_units: Option<usize> = (None, parse_opt_number, [UNTRACKED],
14041414
"divide crate into N units to optimize in parallel"),
1415+
collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
1416+
parse_collapse_macro_debuginfo, [TRACKED],
1417+
"set option to collapse debuginfo for macros"),
14051418
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
14061419
"use Windows Control Flow Guard (default: no)"),
14071420
debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -1550,9 +1563,6 @@ options! {
15501563
"instrument control-flow architecture protection"),
15511564
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
15521565
"the backend to use"),
1553-
collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
1554-
parse_collapse_macro_debuginfo, [TRACKED],
1555-
"set option to collapse debuginfo for macros"),
15561566
combine_cgu: bool = (false, parse_bool, [TRACKED],
15571567
"combine CGUs into a single one"),
15581568
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
@@ -1561,8 +1571,6 @@ options! {
15611571
"threshold to allow cross crate inlining of functions"),
15621572
debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
15631573
"emit discriminators and other data necessary for AutoFDO"),
1564-
debug_macros: bool = (false, parse_bool, [TRACKED],
1565-
"emit line numbers debug info inside macros (default: no)"),
15661574
debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED],
15671575
"compress debug info sections (none, zlib, zstd, default: none)"),
15681576
deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED],

compiler/rustc_span/src/hygiene.rs

+15-23
Original file line numberDiff line numberDiff line change
@@ -459,28 +459,21 @@ impl HygieneData {
459459
span
460460
}
461461

462-
// We need to walk up and update return span if we meet macro instantiation to be collapsed
463-
fn walk_chain_collapsed(
464-
&self,
465-
mut span: Span,
466-
to: Span,
467-
collapse_debuginfo_feature_enabled: bool,
468-
) -> Span {
462+
fn walk_chain_collapsed(&self, mut span: Span, to: Span) -> Span {
469463
let orig_span = span;
470464
let mut ret_span = span;
471-
472-
debug!(
473-
"walk_chain_collapsed({:?}, {:?}), feature_enable={}",
474-
span, to, collapse_debuginfo_feature_enabled,
475-
);
465+
debug!("walk_chain_collapsed({:?}, {:?})", span, to);
476466
debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt());
477-
while !span.eq_ctxt(to) && span.from_expansion() {
478-
let outer_expn = self.outer_expn(span.ctxt());
467+
while let ctxt = span.ctxt()
468+
&& !ctxt.is_root()
469+
&& ctxt != to.ctxt()
470+
{
471+
let outer_expn = self.outer_expn(ctxt);
479472
debug!("walk_chain_collapsed({:?}): outer_expn={:?}", span, outer_expn);
480473
let expn_data = self.expn_data(outer_expn);
481474
debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data);
482475
span = expn_data.call_site;
483-
if !collapse_debuginfo_feature_enabled || expn_data.collapse_debuginfo {
476+
if expn_data.collapse_debuginfo {
484477
ret_span = span;
485478
}
486479
}
@@ -604,14 +597,13 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
604597
HygieneData::with(|data| data.walk_chain(span, to))
605598
}
606599

607-
pub fn walk_chain_collapsed(
608-
span: Span,
609-
to: Span,
610-
collapse_debuginfo_feature_enabled: bool,
611-
) -> Span {
612-
HygieneData::with(|hdata| {
613-
hdata.walk_chain_collapsed(span, to, collapse_debuginfo_feature_enabled)
614-
})
600+
/// In order to have good line stepping behavior in debugger, for the given span we return its
601+
/// outermost macro call site that still has a `#[collapse_debuginfo(yes)]` property on it.
602+
/// We also stop walking call sites at the function body level because no line stepping can occur
603+
/// at the level above that.
604+
/// The returned span can then be used in emitted debuginfo.
605+
pub fn walk_chain_collapsed(span: Span, to: Span) -> Span {
606+
HygieneData::with(|data| data.walk_chain_collapsed(span, to))
615607
}
616608

617609
pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {

src/tools/miri/src/shims/backtrace.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::*;
22
use rustc_ast::ast::Mutability;
33
use rustc_middle::ty::layout::LayoutOf as _;
44
use rustc_middle::ty::{self, Instance, Ty};
5-
use rustc_span::{BytePos, Loc, Symbol};
5+
use rustc_span::{hygiene, BytePos, Loc, Symbol};
66
use rustc_target::{abi::Size, spec::abi::Abi};
77

88
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
@@ -45,12 +45,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
4545

4646
let mut data = Vec::new();
4747
for frame in this.active_thread_stack().iter().rev() {
48-
let mut span = frame.current_span();
49-
// Match the behavior of runtime backtrace spans
50-
// by using a non-macro span in our backtrace. See `FunctionCx::debug_loc`.
51-
if span.from_expansion() && !tcx.sess.opts.unstable_opts.debug_macros {
52-
span = rustc_span::hygiene::walk_chain(span, frame.body.span.ctxt())
53-
}
48+
// Match behavior of debuginfo (`FunctionCx::adjusted_span_and_dbg_scope`).
49+
let span = hygiene::walk_chain_collapsed(frame.current_span(), frame.body.span);
5450
data.push((frame.instance, span.lo()));
5551
}
5652

tests/debuginfo/collapse-debuginfo-external-attr.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// ignore-lldb
2-
#![feature(collapse_debuginfo)]
32

43
// Test that local macro debug info is not collapsed with #[collapse_debuginfo(external)]
54

0 commit comments

Comments
 (0)