about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2025-05-10 15:15:54 +0200
committerUrgau <urgau@numericable.fr>2025-05-26 21:52:21 +0200
commit3fd0265fbb236c8309f2f913cf9946e64818f643 (patch)
tree087850b011c4f037f751da64b1cfae64d5e2c709
parent93f3db25c0e554d3143bed945e2671a14aa5288d (diff)
downloadrust-3fd0265fbb236c8309f2f913cf9946e64818f643.tar.gz
rust-3fd0265fbb236c8309f2f913cf9946e64818f643.zip
rustdoc: use custom `CfgMatchesLintEmitter` to make check-cfg work
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/mod.rs1
-rw-r--r--src/librustdoc/clean/types.rs39
-rw-r--r--src/librustdoc/doctest/rust.rs9
-rw-r--r--tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr12
-rw-r--r--tests/rustdoc-ui/doc-cfg-check-cfg.rs19
-rw-r--r--tests/rustdoc-ui/doc-cfg.rs4
-rw-r--r--tests/rustdoc-ui/doc-cfg.stderr26
8 files changed, 95 insertions, 19 deletions
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 55a116a018a..f25cf606812 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -409,12 +409,12 @@ pub(crate) fn merge_attrs(
             } else {
                 Attributes::from_hir(&both)
             },
-            extract_cfg_from_attrs(both.iter(), cx.tcx, &cx.cache.hidden_cfg),
+            extract_cfg_from_attrs(both.iter(), cx.tcx, None, &cx.cache.hidden_cfg),
         )
     } else {
         (
             Attributes::from_hir(old_attrs),
-            extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
+            extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, None, &cx.cache.hidden_cfg),
         )
     }
 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 28dfa01534e..bacc7b50018 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -210,6 +210,7 @@ fn generate_item_with_correct_attrs(
             Cow::Owned(attr) => attr,
         }),
         cx.tcx,
+        def_id.as_local().map(|did| cx.tcx.local_def_id_to_hir_id(did)),
         &cx.cache.hidden_cfg,
     );
     let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index bb3469867d5..0f92aab5abe 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -12,8 +12,9 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{BodyId, Mutability};
+use rustc_hir::{BodyId, HirId, Mutability};
 use rustc_index::IndexVec;
+use rustc_lint_defs::{BuiltinLintDiag, Lint};
 use rustc_metadata::rendered_const;
 use rustc_middle::span_bug;
 use rustc_middle::ty::fast_reject::SimplifiedType;
@@ -477,7 +478,12 @@ impl Item {
             name,
             kind,
             Attributes::from_hir(hir_attrs),
-            extract_cfg_from_attrs(hir_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
+            extract_cfg_from_attrs(
+                hir_attrs.iter(),
+                cx.tcx,
+                def_id.as_local().map(|did| cx.tcx.local_def_id_to_hir_id(did)),
+                &cx.cache.hidden_cfg,
+            ),
         )
     }
 
@@ -1033,6 +1039,7 @@ pub(crate) fn hir_attr_lists<'a, I: IntoIterator<Item = &'a hir::Attribute>>(
 pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> + Clone>(
     attrs: I,
     tcx: TyCtxt<'_>,
+    hir_id: Option<HirId>,
     hidden_cfg: &FxHashSet<Cfg>,
 ) -> Option<Arc<Cfg>> {
     let doc_cfg_active = tcx.features().doc_cfg();
@@ -1056,6 +1063,32 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
             .peekable();
         if doc_cfg.peek().is_some() && doc_cfg_active {
             let sess = tcx.sess;
+
+            struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, Option<HirId>);
+
+            impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
+                fn emit_span_lint(
+                    &self,
+                    sess: &Session,
+                    lint: &'static Lint,
+                    sp: rustc_span::Span,
+                    builtin_diag: BuiltinLintDiag,
+                ) {
+                    if let Some(hir_id) = self.1 {
+                        self.0.node_span_lint(lint, hir_id, sp, |diag| {
+                            rustc_lint::decorate_builtin_lint(
+                                sess,
+                                Some(self.0),
+                                builtin_diag,
+                                diag,
+                            )
+                        });
+                    } else {
+                        // No HIR id. Probably in another crate. Don't lint.
+                    }
+                }
+            }
+
             doc_cfg.fold(Cfg::True, |mut cfg, item| {
                 if let Some(cfg_mi) =
                     item.meta_item().and_then(|item| rustc_expand::config::parse_cfg(item, sess))
@@ -1064,7 +1097,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
                     rustc_attr_parsing::cfg_matches(
                         cfg_mi,
                         tcx.sess,
-                        rustc_ast::CRATE_NODE_ID,
+                        RustdocCfgMatchesLintEmitter(tcx, hir_id),
                         Some(tcx.features()),
                     );
                     match Cfg::parse(cfg_mi) {
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index f9d2aa3d3b4..a58ab3dd0fc 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -116,9 +116,12 @@ impl HirCollector<'_> {
         nested: F,
     ) {
         let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
-        if let Some(ref cfg) =
-            extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default())
-            && !cfg.matches(&self.tcx.sess.psess)
+        if let Some(ref cfg) = extract_cfg_from_attrs(
+            ast_attrs.iter(),
+            self.tcx,
+            Some(self.tcx.local_def_id_to_hir_id(def_id)),
+            &FxHashSet::default(),
+        ) && !cfg.matches(&self.tcx.sess.psess)
         {
             return;
         }
diff --git a/tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr b/tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr
new file mode 100644
index 00000000000..7e6f8dec5ed
--- /dev/null
+++ b/tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr
@@ -0,0 +1,12 @@
+warning: unexpected `cfg` condition name: `foo`
+  --> $DIR/doc-cfg-check-cfg.rs:13:11
+   |
+LL | #[doc(cfg(foo))]
+   |           ^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(foo)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/rustdoc-ui/doc-cfg-check-cfg.rs b/tests/rustdoc-ui/doc-cfg-check-cfg.rs
index e3420dc0789..6bb520b0726 100644
--- a/tests/rustdoc-ui/doc-cfg-check-cfg.rs
+++ b/tests/rustdoc-ui/doc-cfg-check-cfg.rs
@@ -1,16 +1,21 @@
 // Ensure that `doc(cfg())` respects `check-cfg`
 // Currently not properly working
-#![feature(doc_cfg)]
-#![deny(unexpected_cfgs)]
 
-//@revisions: no_check cfg_empty cfg_foo
+//@ check-pass
+//@ no-auto-check-cfg
+
+//@ revisions: no_check cfg_empty cfg_foo
 //@[cfg_empty] compile-flags: --check-cfg cfg()
 //@[cfg_foo] compile-flags: --check-cfg cfg(foo)
 
-//@[no_check] check-pass
-//@[cfg_empty] check-pass
-//@[cfg_empty] known-bug: #138358
-//@[cfg_foo] check-pass
+#![feature(doc_cfg)]
 
 #[doc(cfg(foo))]
+//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
 pub fn foo() {}
+
+pub mod module {
+    #[allow(unexpected_cfgs)]
+    #[doc(cfg(bar))]
+    pub fn bar() {}
+}
diff --git a/tests/rustdoc-ui/doc-cfg.rs b/tests/rustdoc-ui/doc-cfg.rs
index 354d76bc3c4..14943bbc341 100644
--- a/tests/rustdoc-ui/doc-cfg.rs
+++ b/tests/rustdoc-ui/doc-cfg.rs
@@ -3,7 +3,9 @@
 #[doc(cfg(), cfg(foo, bar))]
 //~^ ERROR
 //~^^ ERROR
-#[doc(cfg(foo), cfg(bar))] // ok!
+#[doc(cfg(foo), cfg(bar))]
+//~^ WARN unexpected `cfg` condition name: `foo`
+//~^^ WARN unexpected `cfg` condition name: `bar`
 #[doc(cfg())] //~ ERROR
 #[doc(cfg(foo, bar))] //~ ERROR
 pub fn foo() {}
diff --git a/tests/rustdoc-ui/doc-cfg.stderr b/tests/rustdoc-ui/doc-cfg.stderr
index 14b7b17e04d..48c8e79ce96 100644
--- a/tests/rustdoc-ui/doc-cfg.stderr
+++ b/tests/rustdoc-ui/doc-cfg.stderr
@@ -10,17 +10,37 @@ error: multiple `cfg` predicates are specified
 LL | #[doc(cfg(), cfg(foo, bar))]
    |                       ^^^
 
+warning: unexpected `cfg` condition name: `foo`
+  --> $DIR/doc-cfg.rs:6:11
+   |
+LL | #[doc(cfg(foo), cfg(bar))]
+   |           ^^^
+   |
+   = help: expected names are: `FALSE` and `test` and 31 more
+   = help: to expect this configuration use `--check-cfg=cfg(foo)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: unexpected `cfg` condition name: `bar`
+  --> $DIR/doc-cfg.rs:6:21
+   |
+LL | #[doc(cfg(foo), cfg(bar))]
+   |                     ^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(bar)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
 error: `cfg` predicate is not specified
-  --> $DIR/doc-cfg.rs:7:7
+  --> $DIR/doc-cfg.rs:9:7
    |
 LL | #[doc(cfg())]
    |       ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
 
 error: multiple `cfg` predicates are specified
-  --> $DIR/doc-cfg.rs:8:16
+  --> $DIR/doc-cfg.rs:10:16
    |
 LL | #[doc(cfg(foo, bar))]
    |                ^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 2 warnings emitted