about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-09-26 18:11:09 +0200
committerGitHub <noreply@github.com>2025-09-26 18:11:09 +0200
commitd09bb02eb50c5b7137eb9a14f546540fa24083cf (patch)
tree1c034166d90e4d2a70709f4e0a0a543b721ae370 /compiler
parent024fbad4a076406e45e4db78c07ac39095ca6a67 (diff)
parent9acc63a48c8206cfe2c2d272600d538983308657 (diff)
downloadrust-d09bb02eb50c5b7137eb9a14f546540fa24083cf.tar.gz
rust-d09bb02eb50c5b7137eb9a14f546540fa24083cf.zip
Rollup merge of #146704 - jdonszelmann:port-debug-visualizer, r=petrochenkov
port `#[debugger_visualizer]` to the new attribute system
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/debugger.rs60
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs4
-rw-r--r--compiler/rustc_hir/src/attrs/data_structures.rs19
-rw-r--r--compiler/rustc_hir/src/attrs/encode_cross_crate.rs1
-rw-r--r--compiler/rustc_middle/src/middle/debugger_visualizer.rs8
-rw-r--r--compiler/rustc_passes/messages.ftl9
-rw-r--r--compiler/rustc_passes/src/check_attr.rs16
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs113
-rw-r--r--compiler/rustc_passes/src/errors.rs17
12 files changed, 143 insertions, 109 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/debugger.rs b/compiler/rustc_attr_parsing/src/attributes/debugger.rs
new file mode 100644
index 00000000000..56ff10be426
--- /dev/null
+++ b/compiler/rustc_attr_parsing/src/attributes/debugger.rs
@@ -0,0 +1,60 @@
+use rustc_hir::attrs::{DebugVisualizer, DebuggerVisualizerType};
+
+use super::prelude::*;
+
+pub(crate) struct DebuggerViualizerParser;
+
+impl<S: Stage> CombineAttributeParser<S> for DebuggerViualizerParser {
+    const PATH: &[Symbol] = &[sym::debugger_visualizer];
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]);
+    const TEMPLATE: AttributeTemplate = template!(
+        List: &[r#"natvis_file = "...", gdb_script_file = "...""#],
+        "https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute"
+    );
+
+    type Item = DebugVisualizer;
+    const CONVERT: ConvertFn<Self::Item> = |v, _| AttributeKind::DebuggerVisualizer(v);
+
+    fn extend<'c>(
+        cx: &'c mut AcceptContext<'_, '_, S>,
+        args: &'c ArgParser<'_>,
+    ) -> impl IntoIterator<Item = Self::Item> + 'c {
+        let Some(l) = args.list() else {
+            cx.expected_list(args.span().unwrap_or(cx.attr_span));
+            return None;
+        };
+        let Some(single) = l.single() else {
+            cx.expected_single_argument(l.span);
+            return None;
+        };
+        let Some(mi) = single.meta_item() else {
+            cx.expected_name_value(single.span(), None);
+            return None;
+        };
+        let path = mi.path().word_sym();
+        let visualizer_type = match path {
+            Some(sym::natvis_file) => DebuggerVisualizerType::Natvis,
+            Some(sym::gdb_script_file) => DebuggerVisualizerType::GdbPrettyPrinter,
+            _ => {
+                cx.expected_specific_argument(
+                    mi.path().span(),
+                    &[sym::natvis_file, sym::gdb_script_file],
+                );
+                return None;
+            }
+        };
+
+        let Some(path) = mi.args().name_value() else {
+            cx.expected_name_value(single.span(), path);
+            return None;
+        };
+
+        let Some(path) = path.value_as_str() else {
+            cx.expected_string_literal(path.value_span, Some(path.value_as_lit()));
+            return None;
+        };
+
+        Some(DebugVisualizer { span: mi.span(), visualizer_type, path })
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 4ed13d239b9..8dbf4c0ef32 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -36,6 +36,7 @@ pub(crate) mod cfg_old;
 pub(crate) mod codegen_attrs;
 pub(crate) mod confusables;
 pub(crate) mod crate_level;
+pub(crate) mod debugger;
 pub(crate) mod deprecation;
 pub(crate) mod dummy;
 pub(crate) mod inline;
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index de1ab5e9578..d7ccf3c7806 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -28,6 +28,7 @@ use crate::attributes::crate_level::{
     CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
     RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser,
 };
+use crate::attributes::debugger::DebuggerViualizerParser;
 use crate::attributes::deprecation::DeprecationParser;
 use crate::attributes::dummy::DummyParser;
 use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
@@ -163,6 +164,7 @@ attribute_parsers!(
         // tidy-alphabetical-start
         Combine<AllowConstFnUnstableParser>,
         Combine<AllowInternalUnstableParser>,
+        Combine<DebuggerViualizerParser>,
         Combine<ForceTargetFeatureParser>,
         Combine<LinkParser>,
         Combine<ReprParser>,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index 7a6dc008c7b..3081badb821 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -2,9 +2,9 @@
 
 use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive;
 use rustc_codegen_ssa::traits::*;
+use rustc_hir::attrs::DebuggerVisualizerType;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::bug;
-use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerType;
 use rustc_session::config::{CrateType, DebugInfo};
 
 use crate::builder::Builder;
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 68a2f43ec67..422b06350e1 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -11,12 +11,12 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
 use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
 use rustc_data_structures::unord::UnordMap;
-use rustc_hir::attrs::OptimizeAttr;
+use rustc_hir::attrs::{DebuggerVisualizerType, OptimizeAttr};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ItemId, Target};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
-use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Dependencies;
 use rustc_middle::middle::exported_symbols::{self, SymbolExportKind};
 use rustc_middle::middle::lang_items;
diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs
index 5481c9debc1..ddcbaeaad88 100644
--- a/compiler/rustc_hir/src/attrs/data_structures.rs
+++ b/compiler/rustc_hir/src/attrs/data_structures.rs
@@ -363,6 +363,20 @@ pub struct LinkEntry {
     pub import_name_type: Option<(PeImportNameType, Span)>,
 }
 
+#[derive(HashStable_Generic, PrintAttribute)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
+pub enum DebuggerVisualizerType {
+    Natvis,
+    GdbPrettyPrinter,
+}
+
+#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
+pub struct DebugVisualizer {
+    pub span: Span,
+    pub visualizer_type: DebuggerVisualizerType,
+    pub path: Symbol,
+}
+
 /// Represents parsed *built-in* inert attributes.
 ///
 /// ## Overview
@@ -485,7 +499,10 @@ pub enum AttributeKind {
     /// Represents `#[custom_mir]`.
     CustomMir(Option<(MirDialect, Span)>, Option<(MirPhase, Span)>, Span),
 
-    ///Represents `#[rustc_deny_explicit_impl]`.
+    /// Represents `#[debugger_visualizer]`.
+    DebuggerVisualizer(ThinVec<DebugVisualizer>),
+
+    /// Represents `#[rustc_deny_explicit_impl]`.
     DenyExplicitImpl(Span),
 
     /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
index e0a37f50f45..1611b865c77 100644
--- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
+++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
@@ -37,6 +37,7 @@ impl AttributeKind {
             Coverage(..) => No,
             CrateName { .. } => No,
             CustomMir(_, _, _) => Yes,
+            DebuggerVisualizer(..) => No,
             DenyExplicitImpl(..) => No,
             Deprecation { .. } => Yes,
             DoNotImplementViaObject(..) => No,
diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
index 5a811321f58..a7f0095dcdf 100644
--- a/compiler/rustc_middle/src/middle/debugger_visualizer.rs
+++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
@@ -1,15 +1,9 @@
 use std::path::PathBuf;
 use std::sync::Arc;
 
+use rustc_hir::attrs::DebuggerVisualizerType;
 use rustc_macros::{Decodable, Encodable, HashStable};
 
-#[derive(HashStable)]
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
-pub enum DebuggerVisualizerType {
-    Natvis,
-    GdbPrettyPrinter,
-}
-
 /// A single debugger visualizer file.
 #[derive(HashStable)]
 #[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 6cd68380e46..870e0a90b54 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -93,15 +93,6 @@ passes_dead_codes =
        }
     } never {$participle}
 
-passes_debug_visualizer_invalid =
-    invalid argument
-    .note_1 = expected: `natvis_file = "..."`
-    .note_2 = OR
-    .note_3 = expected: `gdb_script_file = "..."`
-
-passes_debug_visualizer_placement =
-    attribute should be applied to a module
-
 passes_debug_visualizer_unreadable =
     couldn't read {$file}: {$error}
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index aef123c3721..007353f136d 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -282,6 +282,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     | AttributeKind::ObjcClass { .. }
                     | AttributeKind::ObjcSelector { .. }
                     | AttributeKind::RustcCoherenceIsCore(..)
+                    | AttributeKind::DebuggerVisualizer(..)
                 ) => { /* do nothing  */ }
                 Attribute::Unparsed(attr_item) => {
                     style = Some(attr_item.style);
@@ -302,7 +303,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                             &mut doc_aliases,
                         ),
                         [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target),
-                        [sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target),
                         [sym::rustc_no_implicit_autorefs, ..] => {
                             self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
                         }
@@ -1783,20 +1783,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    /// Checks if the items on the `#[debugger_visualizer]` attribute are valid.
-    fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) {
-        // Here we only check that the #[debugger_visualizer] attribute is attached
-        // to nothing other than a module. All other checks are done in the
-        // `debugger_visualizer` query where they need to be done for decoding
-        // anyway.
-        match target {
-            Target::Mod => {}
-            _ => {
-                self.dcx().emit_err(errors::DebugVisualizerPlacement { span: attr.span() });
-            }
-        }
-    }
-
     /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros.
     /// (Allows proc_macro functions)
     fn check_rustc_allow_const_fn_unstable(
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 7a7a8175e55..7211f3cf85b 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -1,67 +1,60 @@
 //! Detecting usage of the `#[debugger_visualizer]` attribute.
 
-use rustc_ast::Attribute;
+use rustc_ast::ast::NodeId;
+use rustc_ast::{HasNodeId, ItemKind, ast};
+use rustc_attr_parsing::AttributeParser;
 use rustc_expand::base::resolve_path;
-use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
+use rustc_hir::Attribute;
+use rustc_hir::attrs::{AttributeKind, DebugVisualizer};
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::query::{LocalCrate, Providers};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
-use rustc_span::sym;
+use rustc_span::{DUMMY_SP, Span, sym};
 
-use crate::errors::{DebugVisualizerInvalid, DebugVisualizerUnreadable};
+use crate::errors::DebugVisualizerUnreadable;
 
 impl DebuggerVisualizerCollector<'_> {
-    fn check_for_debugger_visualizer(&mut self, attr: &Attribute) {
-        if attr.has_name(sym::debugger_visualizer) {
-            let Some(hints) = attr.meta_item_list() else {
-                self.sess.dcx().emit_err(DebugVisualizerInvalid { span: attr.span });
-                return;
-            };
+    fn check_for_debugger_visualizer(
+        &mut self,
+        attrs: &[ast::Attribute],
+        span: Span,
+        node_id: NodeId,
+    ) {
+        if let Some(Attribute::Parsed(AttributeKind::DebuggerVisualizer(visualizers))) =
+            AttributeParser::parse_limited(
+                &self.sess,
+                attrs,
+                sym::debugger_visualizer,
+                span,
+                node_id,
+                None,
+            )
+        {
+            for DebugVisualizer { span, visualizer_type, path } in visualizers {
+                let file = match resolve_path(&self.sess, path.as_str(), span) {
+                    Ok(file) => file,
+                    Err(err) => {
+                        err.emit();
+                        return;
+                    }
+                };
 
-            let [hint] = hints.as_slice() else {
-                self.sess.dcx().emit_err(DebugVisualizerInvalid { span: attr.span });
-                return;
-            };
-
-            let Some(meta_item) = hint.meta_item() else {
-                self.sess.dcx().emit_err(DebugVisualizerInvalid { span: attr.span });
-                return;
-            };
-
-            let (visualizer_type, visualizer_path) = match (meta_item.name(), meta_item.value_str())
-            {
-                (Some(sym::natvis_file), Some(value)) => (DebuggerVisualizerType::Natvis, value),
-                (Some(sym::gdb_script_file), Some(value)) => {
-                    (DebuggerVisualizerType::GdbPrettyPrinter, value)
-                }
-                (_, _) => {
-                    self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span });
-                    return;
-                }
-            };
-
-            let file = match resolve_path(&self.sess, visualizer_path.as_str(), attr.span) {
-                Ok(file) => file,
-                Err(err) => {
-                    err.emit();
-                    return;
-                }
-            };
-
-            match self.sess.source_map().load_binary_file(&file) {
-                Ok((source, _)) => {
-                    self.visualizers.push(DebuggerVisualizerFile::new(
-                        source,
-                        visualizer_type,
-                        file,
-                    ));
-                }
-                Err(error) => {
-                    self.sess.dcx().emit_err(DebugVisualizerUnreadable {
-                        span: meta_item.span,
-                        file: &file,
-                        error,
-                    });
+                match self.sess.source_map().load_binary_file(&file) {
+                    Ok((source, _)) => {
+                        self.visualizers.push(DebuggerVisualizerFile::new(
+                            source,
+                            visualizer_type,
+                            file,
+                        ));
+                    }
+                    Err(error) => {
+                        self.sess.dcx().emit_err(DebugVisualizerUnreadable {
+                            span,
+                            file: &file,
+                            error,
+                        });
+                    }
                 }
             }
         }
@@ -74,9 +67,15 @@ struct DebuggerVisualizerCollector<'a> {
 }
 
 impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> {
-    fn visit_attribute(&mut self, attr: &'ast Attribute) {
-        self.check_for_debugger_visualizer(attr);
-        rustc_ast::visit::walk_attribute(self, attr);
+    fn visit_item(&mut self, item: &'ast rustc_ast::Item) -> Self::Result {
+        if let ItemKind::Mod(..) = item.kind {
+            self.check_for_debugger_visualizer(&item.attrs, item.span, item.node_id());
+        }
+        rustc_ast::visit::walk_item(self, item);
+    }
+    fn visit_crate(&mut self, krate: &'ast ast::Crate) -> Self::Result {
+        self.check_for_debugger_visualizer(&krate.attrs, DUMMY_SP, krate.id);
+        rustc_ast::visit::walk_crate(self, krate);
     }
 }
 
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index cd8935f6b2f..cfd6b9e6dff 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -476,23 +476,6 @@ pub(crate) struct MacroOnlyAttribute {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_debug_visualizer_placement)]
-pub(crate) struct DebugVisualizerPlacement {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_debug_visualizer_invalid)]
-#[note(passes_note_1)]
-#[note(passes_note_2)]
-#[note(passes_note_3)]
-pub(crate) struct DebugVisualizerInvalid {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_debug_visualizer_unreadable)]
 pub(crate) struct DebugVisualizerUnreadable<'a> {
     #[primary_span]