diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 475dd348e7b63..a94b58f6b44c7 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -16,6 +16,9 @@ expand_attributes_wrong_form = expand_cannot_be_name_of_macro = `{$trait_ident}` cannot be a name of {$macro_type} macro +expand_collapse_debuginfo_illegal = + illegal value {$sym} for attribute #[collapse_debuginfo(no|external|yes)] + expand_count_repetition_misplaced = `count` can not be placed inside the inner-most repetition diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e87f2306bc709..e7260c7637f5d 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -23,7 +23,7 @@ use rustc_session::errors::report_lit_error; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::edition::Edition; -use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; +use rustc_span::hygiene::{AstPass, CollapseDebuginfo, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; @@ -727,7 +727,7 @@ pub struct SyntaxExtension { pub local_inner_macros: bool, /// Should debuginfo for the macro be collapsed to the outermost expansion site (in other /// words, was the macro definition annotated with `#[collapse_debuginfo]`)? - pub collapse_debuginfo: bool, + pub collapse_debuginfo: CollapseDebuginfo, } impl SyntaxExtension { @@ -757,7 +757,26 @@ impl SyntaxExtension { kind, allow_internal_unsafe: false, local_inner_macros: false, - collapse_debuginfo: false, + collapse_debuginfo: CollapseDebuginfo::Unspecified, + } + } + + fn collapse_debuginfo_by_name(sess: &Session, attr: &Attribute) -> CollapseDebuginfo { + if let Some(value) = attr.value_str() { + match value { + sym::no => CollapseDebuginfo::No, + sym::external => CollapseDebuginfo::External, + sym::yes => CollapseDebuginfo::Yes, + _ => { + sess.dcx() + .emit_err(errors::CollapseDebuginfoIllegal { span: attr.span, sym: value }); + CollapseDebuginfo::Unspecified + } + } + } else { + // #[collapse_debuginfo] without enum value (#[collapse_debuginfo(no/external/yes)]) + // considered as `yes` + CollapseDebuginfo::Yes } } @@ -780,7 +799,9 @@ impl SyntaxExtension { let local_inner_macros = attr::find_by_name(attrs, sym::macro_export) .and_then(|macro_export| macro_export.meta_item_list()) .is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros)); - let collapse_debuginfo = attr::contains_name(attrs, sym::collapse_debuginfo); + let collapse_debuginfo = attr::find_by_name(attrs, sym::collapse_debuginfo) + .and_then(|v| Some(Self::collapse_debuginfo_by_name(sess, v))) + .unwrap_or(CollapseDebuginfo::Unspecified); tracing::debug!(?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); let (builtin_name, helper_attrs) = attr::find_by_name(attrs, sym::rustc_builtin_macro) diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 2b43fae6852a1..60aff9a2787f1 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -58,6 +58,14 @@ pub(crate) struct ResolveRelativePath { pub path: String, } +#[derive(Diagnostic)] +#[diag(expand_collapse_debuginfo_illegal)] +pub(crate) struct CollapseDebuginfoIllegal { + #[primary_span] + pub span: Span, + pub sym: Symbol, +} + #[derive(Diagnostic)] #[diag(expand_macro_const_stability)] pub(crate) struct MacroConstStability { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 4442b67df6e28..80cd465f22eb8 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -469,7 +469,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // `#[collapse_debuginfo]` gated!( - collapse_debuginfo, Normal, template!(Word), WarnFollowing, + collapse_debuginfo, Normal, template!(NameValueStr: "no|external|yes|..."), WarnFollowing, experimental!(collapse_debuginfo) ), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index f3f59b05682db..bbd25b027a083 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -3,11 +3,11 @@ use crate::interface::parse_cfg; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ - build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, - FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, - LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, - Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, + build_configuration, build_session_options, rustc_optgroups, BranchProtection, + CollapseDebuginfo, CFGuard, Cfg, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, + ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, + InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, + OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; @@ -742,6 +742,7 @@ fn test_unstable_options_tracking_hash() { }) ); tracked!(codegen_backend, Some("abc".to_string())); + tracked!(collapse_debuginfo, CollapseDebuginfo::Yes); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9e8d7c2ef3ecb..f7fbf307a32a1 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -49,7 +49,7 @@ use rustc_query_system::ich::StableHashingContext; use rustc_serialize::{Decodable, Encodable}; use rustc_session::lint::LintBuffer; pub use rustc_session::lint::RegisteredTools; -use rustc_span::hygiene::MacroKind; +use rustc_span::hygiene::{CollapseDebuginfo, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{hygiene, ExpnId, ExpnKind, Span}; use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx}; @@ -2531,8 +2531,18 @@ impl<'tcx> TyCtxt<'tcx> { if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() { return span; } - let collapse_debuginfo_enabled = self.features().collapse_debuginfo; - hygiene::walk_chain_collapsed(span, upto, collapse_debuginfo_enabled) + let collapse_debuginfo_flag = match self.sess.opts.unstable_opts.collapse_debuginfo { + rustc_session::config::CollapseDebuginfo::Unspecified => CollapseDebuginfo::Unspecified, + rustc_session::config::CollapseDebuginfo::No => CollapseDebuginfo::No, + rustc_session::config::CollapseDebuginfo::External => CollapseDebuginfo::External, + rustc_session::config::CollapseDebuginfo::Yes => CollapseDebuginfo::Yes, + }; + hygiene::walk_chain_collapsed( + span, + upto, + self.features().collapse_debuginfo, + collapse_debuginfo_flag, + ) } #[inline] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 12d8293ecd2f6..293b8339b0c03 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3202,12 +3202,12 @@ pub enum WasiExecModel { /// how the hash should be calculated when adding a new command-line argument. pub(crate) mod dep_tracking { use super::{ - BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression, - ErrorOutputType, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, - LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel, - OutFileName, OutputType, OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks, - SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, - TrimmedDefPaths, WasiExecModel, + BranchProtection, CFGuard, CFProtection, CollapseDebuginfo, CrateType, DebugInfo, + DebugInfoCompression, ErrorOutputType, FunctionReturn, InliningThreshold, + InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, + NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius, + RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, + SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths, WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3286,6 +3286,7 @@ pub(crate) mod dep_tracking { LtoCli, DebugInfo, DebugInfoCompression, + CollapseDebuginfo, UnstableFeatures, NativeLib, SanitizerSet, @@ -3450,6 +3451,25 @@ pub enum ProcMacroExecutionStrategy { CrossThread, } +/// How to perform collapse macros debug info +/// if-ext - if macro from different crate (related to callsite code) +/// | cmd \ attr | no | (unspecified) | external | yes | +/// | no | no | no | no | no | +/// | (unspecified) | no | no | if-ext | yes | +/// | external | no | if-ext | if-ext | yes | +/// | yes | yes | yes | yes | yes | +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum CollapseDebuginfo { + /// Unspecified value + Unspecified = 0, + /// Don't collapse debuginfo for the macro + No = 1, + /// Collapse debuginfo if command line flag enables collapsing + External = 2, + /// Collapse debuginfo for the macro + Yes = 3, +} + /// Which format to use for `-Z dump-mono-stats` #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum DumpMonoStatsFormat { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9c1c1c491b9b7..50b262251005b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -388,6 +388,7 @@ mod desc { pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; pub const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`"; + pub const parse_collapse_debuginfo: &str = "one of `no`, `external`, or `yes`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -1302,6 +1303,16 @@ mod parse { true } + pub(crate) fn parse_collapse_debuginfo(slot: &mut CollapseDebuginfo, v: Option<&str>) -> bool { + *slot = match v { + Some("no") => CollapseDebuginfo::No, + Some("external") => CollapseDebuginfo::External, + Some("yes") => CollapseDebuginfo::Yes, + _ => return false, + }; + true + } + pub(crate) fn parse_proc_macro_execution_strategy( slot: &mut ProcMacroExecutionStrategy, v: Option<&str>, @@ -1534,6 +1545,8 @@ options! { "instrument control-flow architecture protection"), codegen_backend: Option = (None, parse_opt_string, [TRACKED], "the backend to use"), + collapse_debuginfo: CollapseDebuginfo = (CollapseDebuginfo::Unspecified, parse_collapse_debuginfo, [TRACKED], + "set option for collapse macros debug info"), combine_cgu: bool = (false, parse_bool, [TRACKED], "combine CGUs into a single one"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index d03965b539c84..e02840ba5e676 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -163,6 +163,41 @@ pub enum Transparency { Opaque, } +/// How to perform collapse macros debug info +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Encodable, Decodable)] +#[derive(HashStable_Generic)] +pub enum CollapseDebuginfo { + /// Unspecified value + Unspecified = 0, + /// Don't collapse debuginfo for the macro + No = 1, + /// Collapse debuginfo if command line flag enables collapsing + External = 2, + /// Collapse debuginfo for the macro + Yes = 3, +} + +/// if-ext - if macro from different crate (related to callsite code) +/// | cmd \ attr | no | (unspecified) | external | yes | +/// | no | no | no | no | no | +/// | (unspecified) | no | no | if-ext | yes | +/// | external | no | if-ext | if-ext | yes | +/// | yes | yes | yes | yes | yes | +impl CollapseDebuginfo { + pub fn should_collapse(self, flag: CollapseDebuginfo, ext: bool) -> bool { + const NO: bool = false; + const YES: bool = true; + #[rustfmt::skip] + let collapse_table = [ + [NO, NO, NO, NO ], + [NO, NO, ext, YES], + [NO, ext, ext, YES], + [YES, YES, YES, YES], + ]; + collapse_table[flag as usize][self as usize] + } +} + impl LocalExpnId { /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST. pub const ROOT: LocalExpnId = LocalExpnId::from_u32(0); @@ -464,7 +499,8 @@ impl HygieneData { &self, mut span: Span, to: Span, - collapse_debuginfo_enabled: bool, + collapse_debuginfo_feature_enabled: bool, + collapse_debuginfo_flag: CollapseDebuginfo, ) -> Span { let orig_span = span; let mut ret_span = span; @@ -477,7 +513,10 @@ impl HygieneData { let expn_data = self.expn_data(outer_expn); debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data); span = expn_data.call_site; - if !collapse_debuginfo_enabled || expn_data.collapse_debuginfo { + let is_ext = !expn_data.macro_def_id.map_or(false, |v| v.is_local()); + if !collapse_debuginfo_feature_enabled + || expn_data.collapse_debuginfo.should_collapse(collapse_debuginfo_flag, is_ext) + { ret_span = span; } } @@ -601,8 +640,20 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span { HygieneData::with(|data| data.walk_chain(span, to)) } -pub fn walk_chain_collapsed(span: Span, to: Span, collapse_debuginfo_enabled: bool) -> Span { - HygieneData::with(|hdata| hdata.walk_chain_collapsed(span, to, collapse_debuginfo_enabled)) +pub fn walk_chain_collapsed( + span: Span, + to: Span, + collapse_debuginfo_feature_enabled: bool, + collapse_debuginfo_flag: CollapseDebuginfo, +) -> Span { + HygieneData::with(|hdata| { + hdata.walk_chain_collapsed( + span, + to, + collapse_debuginfo_feature_enabled, + collapse_debuginfo_flag, + ) + }) } pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) { @@ -957,7 +1008,7 @@ pub struct ExpnData { pub local_inner_macros: bool, /// Should debuginfo for the macro be collapsed to the outermost expansion site (in other /// words, was the macro definition annotated with `#[collapse_debuginfo]`)? - pub(crate) collapse_debuginfo: bool, + pub(crate) collapse_debuginfo: CollapseDebuginfo, } impl !PartialEq for ExpnData {} @@ -975,7 +1026,7 @@ impl ExpnData { parent_module: Option, allow_internal_unsafe: bool, local_inner_macros: bool, - collapse_debuginfo: bool, + collapse_debuginfo: CollapseDebuginfo, ) -> ExpnData { ExpnData { kind, @@ -1013,7 +1064,7 @@ impl ExpnData { disambiguator: 0, allow_internal_unsafe: false, local_inner_macros: false, - collapse_debuginfo: false, + collapse_debuginfo: CollapseDebuginfo::Unspecified, } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8ed1255c010f1..b61b3243c8389 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -748,6 +748,7 @@ symbols! { extern_in_paths, extern_prelude, extern_types, + external, external_doc, f, f16c_target_feature, @@ -1810,6 +1811,7 @@ symbols! { xmm_reg, yeet_desugar_details, yeet_expr, + yes, yield_expr, ymm_reg, zmm_reg,