Skip to content

Commit 6acb9e7

Browse files
committed
Auto merge of #120845 - petrochenkov:debmac, r=oli-obk
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) - #100758 (comment) describes some debugging scenarios that motivate this default as reasonable. `#[collapse_debuginfo]` attribute without a value is no longer supported to avoid guessing the default. Stabilization report: #120845 (comment) Closes #100758 Closes #41743 Closes #39153
2 parents e59f2c5 + 683ad6b commit 6acb9e7

32 files changed

+211
-339
lines changed

compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use cranelift_codegen::binemit::CodeOffset;
77
use cranelift_codegen::MachSrcLoc;
88
use gimli::write::{AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable};
99
use rustc_span::{
10-
FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
10+
hygiene, FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
1111
};
1212

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

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
@@ -789,55 +789,50 @@ impl SyntaxExtension {
789789
}
790790
}
791791

792-
fn collapse_debuginfo_by_name(sess: &Session, attr: &Attribute) -> CollapseMacroDebuginfo {
793-
use crate::errors::CollapseMacroDebuginfoIllegal;
794-
// #[collapse_debuginfo] without enum value (#[collapse_debuginfo(no/external/yes)])
795-
// considered as `yes`
796-
attr.meta_item_list().map_or(CollapseMacroDebuginfo::Yes, |l| {
797-
let [NestedMetaItem::MetaItem(item)] = &l[..] else {
798-
sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: attr.span });
799-
return CollapseMacroDebuginfo::Unspecified;
800-
};
801-
if !item.is_word() {
802-
sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span });
803-
CollapseMacroDebuginfo::Unspecified
804-
} else {
805-
match item.name_or_empty() {
806-
sym::no => CollapseMacroDebuginfo::No,
807-
sym::external => CollapseMacroDebuginfo::External,
808-
sym::yes => CollapseMacroDebuginfo::Yes,
809-
_ => {
810-
sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span });
811-
CollapseMacroDebuginfo::Unspecified
812-
}
813-
}
814-
}
815-
})
792+
fn collapse_debuginfo_by_name(attr: &Attribute) -> Result<CollapseMacroDebuginfo, Span> {
793+
let list = attr.meta_item_list();
794+
let Some([NestedMetaItem::MetaItem(item)]) = list.as_deref() else {
795+
return Err(attr.span);
796+
};
797+
if !item.is_word() {
798+
return Err(item.span);
799+
}
800+
801+
match item.name_or_empty() {
802+
sym::no => Ok(CollapseMacroDebuginfo::No),
803+
sym::external => Ok(CollapseMacroDebuginfo::External),
804+
sym::yes => Ok(CollapseMacroDebuginfo::Yes),
805+
_ => Err(item.path.span),
806+
}
816807
}
817808

818809
/// if-ext - if macro from different crate (related to callsite code)
819810
/// | cmd \ attr | no | (unspecified) | external | yes |
820811
/// | no | no | no | no | no |
821-
/// | (unspecified) | no | no | if-ext | yes |
812+
/// | (unspecified) | no | if-ext | if-ext | yes |
822813
/// | external | no | if-ext | if-ext | yes |
823814
/// | yes | yes | yes | yes | yes |
824-
fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool {
825-
let mut collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
826-
.map(|v| Self::collapse_debuginfo_by_name(sess, v))
827-
.unwrap_or(CollapseMacroDebuginfo::Unspecified);
828-
if collapse_debuginfo_attr == CollapseMacroDebuginfo::Unspecified
829-
&& attr::contains_name(attrs, sym::rustc_builtin_macro)
830-
{
831-
collapse_debuginfo_attr = CollapseMacroDebuginfo::Yes;
832-
}
833-
834-
let flag = sess.opts.unstable_opts.collapse_macro_debuginfo;
835-
let attr = collapse_debuginfo_attr;
836-
let ext = !is_local;
815+
fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], ext: bool) -> bool {
816+
let flag = sess.opts.cg.collapse_macro_debuginfo;
817+
let attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
818+
.and_then(|attr| {
819+
Self::collapse_debuginfo_by_name(attr)
820+
.map_err(|span| {
821+
sess.dcx().emit_err(errors::CollapseMacroDebuginfoIllegal { span })
822+
})
823+
.ok()
824+
})
825+
.unwrap_or_else(|| {
826+
if attr::contains_name(attrs, sym::rustc_builtin_macro) {
827+
CollapseMacroDebuginfo::Yes
828+
} else {
829+
CollapseMacroDebuginfo::Unspecified
830+
}
831+
});
837832
#[rustfmt::skip]
838833
let collapse_table = [
839834
[false, false, false, false],
840-
[false, false, ext, true],
835+
[false, ext, ext, true],
841836
[false, ext, ext, true],
842837
[true, true, true, true],
843838
];
@@ -864,7 +859,7 @@ impl SyntaxExtension {
864859
let local_inner_macros = attr::find_by_name(attrs, sym::macro_export)
865860
.and_then(|macro_export| macro_export.meta_item_list())
866861
.is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros));
867-
let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, is_local);
862+
let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local);
868863
tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
869864

870865
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
@@ -98,6 +98,8 @@ declare_features! (
9898
(accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
9999
/// Allows using the CMPXCHG16B target feature.
100100
(accepted, cmpxchg16b_target_feature, "1.69.0", Some(44839)),
101+
/// Allows use of the `#[collapse_debuginfo]` attribute.
102+
(accepted, collapse_debuginfo, "CURRENT_RUSTC_VERSION", Some(100758)),
101103
/// Allows usage of the `compile_error!` macro.
102104
(accepted, compile_error, "1.20.0", Some(40872)),
103105
/// Allows `impl Trait` in function return types.

compiler/rustc_feature/src/builtin_attrs.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
450450
template!(List: r#"natvis_file = "...", gdb_script_file = "...""#),
451451
DuplicatesOk, EncodeCrossCrate::No
452452
),
453+
ungated!(collapse_debuginfo, Normal, template!(List: "no|external|yes"), ErrorFollowing,
454+
EncodeCrossCrate::Yes
455+
),
453456

454457
// ==========================================================================
455458
// Unstable attributes:
@@ -516,12 +519,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
516519
EncodeCrossCrate::Yes, experimental!(deprecated_safe),
517520
),
518521

519-
// `#[collapse_debuginfo]`
520-
gated!(
521-
collapse_debuginfo, Normal, template!(Word, List: "no|external|yes"), ErrorFollowing,
522-
EncodeCrossCrate::No, experimental!(collapse_debuginfo)
523-
),
524-
525522
// RFC 2397
526523
gated!(
527524
do_not_recommend, Normal, template!(Word), WarnFollowing,

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,6 @@ declare_features! (
395395
(unstable, closure_track_caller, "1.57.0", Some(87417)),
396396
/// Allows to use the `#[cmse_nonsecure_entry]` attribute.
397397
(unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)),
398-
/// Allows use of the `#[collapse_debuginfo]` attribute.
399-
(unstable, collapse_debuginfo, "1.65.0", Some(100758)),
400398
/// Allows `async {}` expressions in const contexts.
401399
(unstable, const_async_blocks, "1.53.0", Some(85368)),
402400
/// Allows `const || {}` closures in const contexts.

compiler/rustc_interface/src/tests.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ fn test_codegen_options_tracking_hash() {
600600
// Make sure that changing a [TRACKED] option changes the hash.
601601
// tidy-alphabetical-start
602602
tracked!(code_model, Some(CodeModel::Large));
603+
tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes);
603604
tracked!(control_flow_guard, CFGuard::Checks);
604605
tracked!(debug_assertions, Some(true));
605606
tracked!(debuginfo, DebugInfo::Limited);
@@ -760,12 +761,10 @@ fn test_unstable_options_tracking_hash() {
760761
})
761762
);
762763
tracked!(codegen_backend, Some("abc".to_string()));
763-
tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes);
764764
tracked!(coverage_options, CoverageOptions { branch: true, mcdc: true });
765765
tracked!(crate_attr, vec!["abc".to_string()]);
766766
tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
767767
tracked!(debug_info_for_profiling, true);
768-
tracked!(debug_macros, true);
769768
tracked!(default_hidden_visibility, Some(true));
770769
tracked!(dep_info_omit_d_target, true);
771770
tracked!(direct_access_external_data, Some(true));

compiler/rustc_middle/src/ty/mod.rs

+1-17
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use rustc_session::lint::LintBuffer;
5454
pub use rustc_session::lint::RegisteredTools;
5555
use rustc_span::hygiene::MacroKind;
5656
use rustc_span::symbol::{kw, sym, Ident, Symbol};
57-
use rustc_span::{hygiene, ExpnId, ExpnKind, Span};
57+
use rustc_span::{ExpnId, ExpnKind, Span};
5858
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
5959
pub use rustc_target::abi::{ReprFlags, ReprOptions};
6060
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
@@ -2013,22 +2013,6 @@ impl<'tcx> TyCtxt<'tcx> {
20132013
(ident, scope)
20142014
}
20152015

2016-
/// Returns corrected span if the debuginfo for `span` should be collapsed to the outermost
2017-
/// expansion site (with collapse_debuginfo attribute if the corresponding feature enabled).
2018-
/// Only applies when `Span` is the result of macro expansion.
2019-
///
2020-
/// - If the `collapse_debuginfo` feature is enabled then debuginfo is not collapsed by default
2021-
/// and only when a (some enclosing) macro definition is annotated with `#[collapse_debuginfo]`.
2022-
/// - If `collapse_debuginfo` is not enabled, then debuginfo is collapsed by default.
2023-
///
2024-
/// When `-Zdebug-macros` is provided then debuginfo will never be collapsed.
2025-
pub fn collapsed_debuginfo(self, span: Span, upto: Span) -> Span {
2026-
if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() {
2027-
return span;
2028-
}
2029-
hygiene::walk_chain_collapsed(span, upto, self.features().collapse_debuginfo)
2030-
}
2031-
20322016
#[inline]
20332017
pub fn is_const_fn_raw(self, def_id: DefId) -> bool {
20342018
matches!(

compiler/rustc_session/src/options.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -1358,10 +1358,20 @@ mod parse {
13581358
slot: &mut CollapseMacroDebuginfo,
13591359
v: Option<&str>,
13601360
) -> bool {
1361+
if v.is_some() {
1362+
let mut bool_arg = None;
1363+
if parse_opt_bool(&mut bool_arg, v) {
1364+
*slot = if bool_arg.unwrap() {
1365+
CollapseMacroDebuginfo::Yes
1366+
} else {
1367+
CollapseMacroDebuginfo::No
1368+
};
1369+
return true;
1370+
}
1371+
}
1372+
13611373
*slot = match v {
1362-
Some("no") => CollapseMacroDebuginfo::No,
13631374
Some("external") => CollapseMacroDebuginfo::External,
1364-
Some("yes") => CollapseMacroDebuginfo::Yes,
13651375
_ => return false,
13661376
};
13671377
true
@@ -1460,6 +1470,9 @@ options! {
14601470
"choose the code model to use (`rustc --print code-models` for details)"),
14611471
codegen_units: Option<usize> = (None, parse_opt_number, [UNTRACKED],
14621472
"divide crate into N units to optimize in parallel"),
1473+
collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
1474+
parse_collapse_macro_debuginfo, [TRACKED],
1475+
"set option to collapse debuginfo for macros"),
14631476
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
14641477
"use Windows Control Flow Guard (default: no)"),
14651478
debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -1607,9 +1620,6 @@ options! {
16071620
"show all expected values in check-cfg diagnostics (default: no)"),
16081621
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
16091622
"the backend to use"),
1610-
collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
1611-
parse_collapse_macro_debuginfo, [TRACKED],
1612-
"set option to collapse debuginfo for macros"),
16131623
combine_cgu: bool = (false, parse_bool, [TRACKED],
16141624
"combine CGUs into a single one"),
16151625
coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED],
@@ -1620,8 +1630,6 @@ options! {
16201630
"threshold to allow cross crate inlining of functions"),
16211631
debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
16221632
"emit discriminators and other data necessary for AutoFDO"),
1623-
debug_macros: bool = (false, parse_bool, [TRACKED],
1624-
"emit line numbers debug info inside macros (default: no)"),
16251633
debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED],
16261634
"compress debug info sections (none, zlib, zstd, default: none)"),
16271635
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/doc/rustc/src/codegen-options/index.md

+12
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ generated code, but may be slower to compile.
4242
The default value, if not specified, is 16 for non-incremental builds. For
4343
incremental builds the default is 256 which allows caching to be more granular.
4444

45+
## collapse-macro-debuginfo
46+
47+
This flag controls whether code locations from a macro definition are collapsed into a single
48+
location associated with that macro's call site, when generating debuginfo for this crate.
49+
50+
This option, if passed, overrides both default collapsing behavior and `#[collapse_debuginfo]`
51+
attributes in code.
52+
53+
* `y`, `yes`, `on`, `true`: collapse code locations in debuginfo.
54+
* `n`, `no`, `off` or `false`: do not collapse code locations in debuginfo.
55+
* `external`: collapse code locations in debuginfo only if the macro comes from a different crate.
56+
4557
## control-flow-guard
4658

4759
This flag controls whether LLVM enables the Windows [Control Flow

0 commit comments

Comments
 (0)