about summary refs log tree commit diff
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs88
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs113
-rw-r--r--compiler/rustc_passes/src/errors.rs37
3 files changed, 132 insertions, 106 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 94c9e71ce77..4ea237cfa03 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -10,7 +10,7 @@ use std::collections::hash_map::Entry;
 use std::slice;
 
 use rustc_abi::{Align, ExternAbi, Size};
-use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast};
+use rustc_ast::{AttrStyle, LitKind, MetaItem, MetaItemInner, MetaItemKind, ast};
 use rustc_attr_parsing::{AttributeParser, Late};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
@@ -256,6 +256,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     | AttributeKind::MacroEscape( .. )
                     | AttributeKind::RustcLayoutScalarValidRangeStart(..)
                     | AttributeKind::RustcLayoutScalarValidRangeEnd(..)
+                    | AttributeKind::RustcSimdMonomorphizeLaneLimit(..)
                     | AttributeKind::ExportStable
                     | AttributeKind::FfiConst(..)
                     | AttributeKind::UnstableFeatureBound(..)
@@ -281,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);
@@ -301,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)
                         }
@@ -1159,16 +1160,59 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    /// Check that the `#![doc(cfg_hide(...))]` attribute only contains a list of attributes.
-    ///
-    fn check_doc_cfg_hide(&self, meta: &MetaItemInner, hir_id: HirId) {
-        if meta.meta_item_list().is_none() {
-            self.tcx.emit_node_span_lint(
-                INVALID_DOC_ATTRIBUTES,
-                hir_id,
-                meta.span(),
-                errors::DocCfgHideTakesList,
-            );
+    /// Check that the `#![doc(auto_cfg)]` attribute has the expected input.
+    fn check_doc_auto_cfg(&self, meta: &MetaItem, hir_id: HirId) {
+        match &meta.kind {
+            MetaItemKind::Word => {}
+            MetaItemKind::NameValue(lit) => {
+                if !matches!(lit.kind, LitKind::Bool(_)) {
+                    self.tcx.emit_node_span_lint(
+                        INVALID_DOC_ATTRIBUTES,
+                        hir_id,
+                        meta.span,
+                        errors::DocAutoCfgWrongLiteral,
+                    );
+                }
+            }
+            MetaItemKind::List(list) => {
+                for item in list {
+                    let Some(attr_name @ (sym::hide | sym::show)) = item.name() else {
+                        self.tcx.emit_node_span_lint(
+                            INVALID_DOC_ATTRIBUTES,
+                            hir_id,
+                            meta.span,
+                            errors::DocAutoCfgExpectsHideOrShow,
+                        );
+                        continue;
+                    };
+                    if let Some(list) = item.meta_item_list() {
+                        for item in list {
+                            let valid = item.meta_item().is_some_and(|meta| {
+                                meta.path.segments.len() == 1
+                                    && matches!(
+                                        &meta.kind,
+                                        MetaItemKind::Word | MetaItemKind::NameValue(_)
+                                    )
+                            });
+                            if !valid {
+                                self.tcx.emit_node_span_lint(
+                                    INVALID_DOC_ATTRIBUTES,
+                                    hir_id,
+                                    item.span(),
+                                    errors::DocAutoCfgHideShowUnexpectedItem { attr_name },
+                                );
+                            }
+                        }
+                    } else {
+                        self.tcx.emit_node_span_lint(
+                            INVALID_DOC_ATTRIBUTES,
+                            hir_id,
+                            meta.span,
+                            errors::DocAutoCfgHideShowExpectsList { attr_name },
+                        );
+                    }
+                }
+            }
         }
     }
 
@@ -1244,10 +1288,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                             self.check_attr_crate_level(attr, style, meta, hir_id);
                         }
 
-                        Some(sym::cfg_hide) => {
-                            if self.check_attr_crate_level(attr, style, meta, hir_id) {
-                                self.check_doc_cfg_hide(meta, hir_id);
-                            }
+                        Some(sym::auto_cfg) => {
+                            self.check_doc_auto_cfg(i_meta, hir_id);
                         }
 
                         Some(sym::inline | sym::no_inline) => {
@@ -1782,20 +1824,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..f0726014e0a 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -309,8 +309,24 @@ pub(crate) struct DocTestLiteral;
 pub(crate) struct DocTestTakesList;
 
 #[derive(LintDiagnostic)]
-#[diag(passes_doc_cfg_hide_takes_list)]
-pub(crate) struct DocCfgHideTakesList;
+#[diag(passes_doc_auto_cfg_wrong_literal)]
+pub(crate) struct DocAutoCfgWrongLiteral;
+
+#[derive(LintDiagnostic)]
+#[diag(passes_doc_auto_cfg_expects_hide_or_show)]
+pub(crate) struct DocAutoCfgExpectsHideOrShow;
+
+#[derive(LintDiagnostic)]
+#[diag(passes_doc_auto_cfg_hide_show_expects_list)]
+pub(crate) struct DocAutoCfgHideShowExpectsList {
+    pub attr_name: Symbol,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_doc_auto_cfg_hide_show_unexpected_item)]
+pub(crate) struct DocAutoCfgHideShowUnexpectedItem {
+    pub attr_name: Symbol,
+}
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_test_unknown_any)]
@@ -476,23 +492,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]