diff options
| author | Urgau <urgau@numericable.fr> | 2025-05-10 15:15:54 +0200 |
|---|---|---|
| committer | Urgau <urgau@numericable.fr> | 2025-05-26 21:52:21 +0200 |
| commit | 3fd0265fbb236c8309f2f913cf9946e64818f643 (patch) | |
| tree | 087850b011c4f037f751da64b1cfae64d5e2c709 | |
| parent | 93f3db25c0e554d3143bed945e2671a14aa5288d (diff) | |
| download | rust-3fd0265fbb236c8309f2f913cf9946e64818f643.tar.gz rust-3fd0265fbb236c8309f2f913cf9946e64818f643.zip | |
rustdoc: use custom `CfgMatchesLintEmitter` to make check-cfg work
| -rw-r--r-- | src/librustdoc/clean/inline.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 1 | ||||
| -rw-r--r-- | src/librustdoc/clean/types.rs | 39 | ||||
| -rw-r--r-- | src/librustdoc/doctest/rust.rs | 9 | ||||
| -rw-r--r-- | tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr | 12 | ||||
| -rw-r--r-- | tests/rustdoc-ui/doc-cfg-check-cfg.rs | 19 | ||||
| -rw-r--r-- | tests/rustdoc-ui/doc-cfg.rs | 4 | ||||
| -rw-r--r-- | tests/rustdoc-ui/doc-cfg.stderr | 26 |
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 |
