Update check_doc_cfg pass in rustdoc, remove old rustc_attr_parsing::cfg_matches API

This commit is contained in:
Guillaume Gomez 2025-12-04 12:58:31 +01:00
parent 9c8c67bfdd
commit d1277ccffa
2 changed files with 49 additions and 91 deletions

View file

@ -4,8 +4,6 @@ use rustc_feature::{Features, GatedCfg, find_gated_cfg};
use rustc_hir::RustcVersion;
use rustc_hir::lints::AttributeLintKind;
use rustc_session::Session;
use rustc_session::config::ExpectedValues;
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
use rustc_session::lint::{BuiltinLintDiag, Lint};
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
@ -37,44 +35,6 @@ pub struct Condition {
pub span: Span,
}
/// Tests if a cfg-pattern matches the cfg set
pub fn cfg_matches(
cfg: &MetaItemInner,
sess: &Session,
lint_emitter: impl CfgMatchesLintEmitter,
features: Option<&Features>,
) -> bool {
eval_condition(cfg, sess, features, &mut |cfg| {
try_gate_cfg(cfg.name, cfg.span, sess, features);
match sess.psess.check_config.expecteds.get(&cfg.name) {
Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
lint_emitter.emit_span_lint(
sess,
UNEXPECTED_CFGS,
cfg.span,
BuiltinLintDiag::AttributeLint(AttributeLintKind::UnexpectedCfgValue(
(cfg.name, cfg.name_span),
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
)),
);
}
None if sess.psess.check_config.exhaustive_names => {
lint_emitter.emit_span_lint(
sess,
UNEXPECTED_CFGS,
cfg.span,
BuiltinLintDiag::AttributeLint(AttributeLintKind::UnexpectedCfgName(
(cfg.name, cfg.name_span),
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
)),
);
}
_ => { /* not unexpected */ }
}
sess.psess.config.contains(&(cfg.name, cfg.value))
})
}
pub fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
let gate = find_gated_cfg(|sym| sym == name);
if let (Some(feats), Some(gated_cfg)) = (features, gate) {

View file

@ -1,9 +1,8 @@
#![allow(dead_code, unused_imports)]
use rustc_hir::HirId;
use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{Attribute, HirId};
use rustc_middle::ty::TyCtxt;
use rustc_span::sym;
use super::Pass;
use crate::clean::{Attributes, Crate, Item};
@ -16,59 +15,58 @@ pub(crate) const CHECK_DOC_CFG: Pass = Pass {
description: "checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs",
};
pub(crate) fn check_doc_cfg(krate: Crate, _cx: &mut DocContext<'_>) -> Crate {
// let mut checker = DocCfgChecker { cx };
// checker.visit_crate(&krate);
pub(crate) fn check_doc_cfg(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
let mut checker = DocCfgChecker { cx };
checker.visit_crate(&krate);
krate
}
// struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, HirId);
struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, HirId);
// impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
// fn emit_span_lint(
// &self,
// sess: &rustc_session::Session,
// lint: &'static rustc_lint::Lint,
// sp: rustc_span::Span,
// builtin_diag: rustc_lint_defs::BuiltinLintDiag,
// ) {
// self.0.node_span_lint(lint, self.1, sp, |diag| {
// rustc_lint::decorate_builtin_lint(sess, Some(self.0), builtin_diag, diag)
// });
// }
// }
impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
fn emit_span_lint(
&self,
sess: &rustc_session::Session,
lint: &'static rustc_lint::Lint,
sp: rustc_span::Span,
builtin_diag: rustc_lint_defs::BuiltinLintDiag,
) {
self.0.node_span_lint(lint, self.1, sp, |diag| {
rustc_lint::decorate_builtin_lint(sess, Some(self.0), builtin_diag, diag)
});
}
}
// struct DocCfgChecker<'a, 'tcx> {
// cx: &'a mut DocContext<'tcx>,
// }
struct DocCfgChecker<'a, 'tcx> {
cx: &'a mut DocContext<'tcx>,
}
// impl DocCfgChecker<'_, '_> {
// fn check_attrs(&mut self, attrs: &Attributes, did: LocalDefId) {
// for attr in &attrs.other_attrs {
// let Attribute::Parsed(AttributeKind::Doc(d)) = attr else { continue };
// let Some(doc_cfg) = d.cfg else { continue };
impl DocCfgChecker<'_, '_> {
fn check_attrs(&mut self, attrs: &Attributes, did: LocalDefId) {
for attr in &attrs.other_attrs {
let Attribute::Parsed(AttributeKind::Doc(d)) = attr else { continue };
// if let Some([cfg_mi]) = doc_cfg.meta_item_list() {
// let _ = rustc_attr_parsing::cfg_matches(
// cfg_mi,
// &self.cx.tcx.sess,
// RustdocCfgMatchesLintEmitter(
// self.cx.tcx,
// self.cx.tcx.local_def_id_to_hir_id(did),
// ),
// Some(self.cx.tcx.features()),
// );
// }
// }
// }
// }
for doc_cfg in &d.cfg {
let _ = eval_config_entry(
&self.cx.tcx.sess,
doc_cfg,
&RustdocCfgMatchesLintEmitter(
self.cx.tcx,
self.cx.tcx.local_def_id_to_hir_id(did),
),
ShouldEmit::ErrorsAndLints,
);
}
}
}
}
// impl DocVisitor<'_> for DocCfgChecker<'_, '_> {
// fn visit_item(&mut self, item: &'_ Item) {
// if let Some(Some(local_did)) = item.def_id().map(|did| did.as_local()) {
// self.check_attrs(&item.attrs, local_did);
// }
impl DocVisitor<'_> for DocCfgChecker<'_, '_> {
fn visit_item(&mut self, item: &'_ Item) {
if let Some(Some(local_did)) = item.def_id().map(|did| did.as_local()) {
self.check_attrs(&item.attrs, local_did);
}
// self.visit_item_recur(item);
// }
// }
self.visit_item_recur(item);
}
}