Auto merge of #151162 - GuillaumeGomez:cleanup-attr-parsing, r=JonathanBrouwer

Clean up `rustc_attr_parsing`

Follow-up of rust-lang/rust#150934.

It removes the `Option<>` wrapping for `SharedContext::target` field and completely removed the `target_id` field. Considering this type contains a closure and never updates its `target_id` field, there is no need to keep it around, it can be used directly in the lint emitter.

r? @JonathanBrouwer
This commit is contained in:
bors 2026-01-16 13:03:57 +00:00
commit b08c11df4b
11 changed files with 57 additions and 61 deletions

View file

@ -51,7 +51,7 @@ use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
use rustc_hir::lints::DelayedLint;
use rustc_hir::lints::{AttributeLint, DelayedLint};
use rustc_hir::{
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
LifetimeSyntax, ParamName, Target, TraitCandidate, find_attr,
@ -1022,12 +1022,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.attribute_parser.parse_attribute_list(
attrs,
target_span,
target_hir_id,
target,
OmitDoc::Lower,
|s| l.lower(s),
|l| {
self.delayed_lints.push(DelayedLint::AttributeParsing(l));
|lint_id, span, kind| {
self.delayed_lints.push(DelayedLint::AttributeParsing(AttributeLint {
lint_id,
id: target_hir_id,
span,
kind,
}));
},
)
}

View file

@ -9,7 +9,7 @@ use rustc_feature::{
};
use rustc_hir::attrs::CfgEntry;
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{AttrPath, RustcVersion};
use rustc_hir::{AttrPath, RustcVersion, Target};
use rustc_parse::parser::{ForceCollect, Parser};
use rustc_parse::{exp, parse_in};
use rustc_session::Session;
@ -373,6 +373,7 @@ fn parse_cfg_attr_internal<'a>(
ParsedDescription::Attribute,
pred_span,
CRATE_NODE_ID,
Target::Crate,
features,
ShouldEmit::ErrorsAndLints,
&meta,

View file

@ -2,8 +2,8 @@ use rustc_ast::token::Token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrStyle, NodeId, token};
use rustc_feature::{AttributeTemplate, Features};
use rustc_hir::AttrPath;
use rustc_hir::attrs::CfgEntry;
use rustc_hir::{AttrPath, Target};
use rustc_parse::exp;
use rustc_parse::parser::Parser;
use rustc_session::Session;
@ -91,6 +91,8 @@ pub fn parse_cfg_select(
ParsedDescription::Macro,
cfg_span,
lint_node_id,
// Doesn't matter what the target actually is here.
Target::Crate,
features,
ShouldEmit::ErrorsAndLints,
&meta,

View file

@ -50,7 +50,7 @@ fn check_attr_not_crate_level<S: Stage>(
span: Span,
attr_name: Symbol,
) -> bool {
if cx.shared.target.is_some_and(|target| target == Target::Crate) {
if cx.shared.target == Target::Crate {
cx.emit_err(DocAttrNotCrateLevel { span, attr_name });
return false;
}
@ -59,7 +59,7 @@ fn check_attr_not_crate_level<S: Stage>(
/// Checks that an attribute is used at the crate level. Returns `true` if valid.
fn check_attr_crate_level<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, span: Span) -> bool {
if cx.shared.target.is_some_and(|target| target != Target::Crate) {
if cx.shared.target != Target::Crate {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::AttrCrateLevelOnly,

View file

@ -8,7 +8,7 @@ use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
use rustc_errors::{Diag, Diagnostic, Level};
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{AttrPath, HirId};
use rustc_session::Session;
use rustc_session::lint::{Lint, LintId};
@ -419,8 +419,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
) {
return;
}
let id = self.target_id;
(self.emit_lint)(AttributeLint { lint_id: LintId::of(lint), id, span, kind });
(self.emit_lint)(LintId::of(lint), span, kind);
}
pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
@ -665,11 +664,11 @@ pub struct SharedContext<'p, 'sess, S: Stage> {
pub(crate) cx: &'p mut AttributeParser<'sess, S>,
/// The span of the syntactical component this attribute was applied to
pub(crate) target_span: Span,
/// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
pub(crate) target_id: S::Id,
pub(crate) target: Option<rustc_hir::Target>,
pub(crate) target: rustc_hir::Target,
pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
/// The second argument of the closure is a [`NodeId`] if `S` is `Early` and a [`HirId`] if `S`
/// is `Late` and is the ID of the syntactical component this attribute was applied to.
pub(crate) emit_lint: &'p mut dyn FnMut(LintId, Span, AttributeLintKind),
}
/// Context given to every attribute parser during finalization.

View file

@ -6,10 +6,10 @@ use rustc_ast::{AttrItemKind, AttrStyle, NodeId, Safety};
use rustc_errors::DiagCtxtHandle;
use rustc_feature::{AttributeTemplate, Features};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::AttributeLint;
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
use rustc_session::Session;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::{BuiltinLintDiag, LintId};
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
use crate::context::{AcceptContext, FinalizeContext, SharedContext, Stage};
@ -113,16 +113,15 @@ impl<'sess> AttributeParser<'sess, Early> {
p.parse_attribute_list(
attrs,
target_span,
target_node_id,
target,
OmitDoc::Skip,
std::convert::identity,
|lint| {
|lint_id, span, kind| {
sess.psess.buffer_lint(
lint.lint_id.lint,
lint.span,
lint.id,
BuiltinLintDiag::AttributeLint(lint.kind),
lint_id.lint,
span,
target_node_id,
BuiltinLintDiag::AttributeLint(kind),
)
},
)
@ -135,6 +134,7 @@ impl<'sess> AttributeParser<'sess, Early> {
attr: &ast::Attribute,
target_span: Span,
target_node_id: NodeId,
target: Target,
features: Option<&'sess Features>,
emit_errors: ShouldEmit,
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser) -> Option<T>,
@ -163,6 +163,7 @@ impl<'sess> AttributeParser<'sess, Early> {
ParsedDescription::Attribute,
target_span,
target_node_id,
target,
features,
emit_errors,
&args,
@ -183,6 +184,7 @@ impl<'sess> AttributeParser<'sess, Early> {
parsed_description: ParsedDescription,
target_span: Span,
target_node_id: NodeId,
target: Target,
features: Option<&'sess Features>,
emit_errors: ShouldEmit,
args: &I,
@ -196,29 +198,22 @@ impl<'sess> AttributeParser<'sess, Early> {
sess,
stage: Early { emit_errors },
};
let mut emit_lint = |lint: AttributeLint<NodeId>| {
let mut emit_lint = |lint_id: LintId, span: Span, kind: AttributeLintKind| {
sess.psess.buffer_lint(
lint.lint_id.lint,
lint.span,
lint.id,
BuiltinLintDiag::AttributeLint(lint.kind),
lint_id.lint,
span,
target_node_id,
BuiltinLintDiag::AttributeLint(kind),
)
};
if let Some(safety) = attr_safety {
parser.check_attribute_safety(
&attr_path,
inner_span,
safety,
&mut emit_lint,
target_node_id,
)
parser.check_attribute_safety(&attr_path, inner_span, safety, &mut emit_lint)
}
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
shared: SharedContext {
cx: &mut parser,
target_span,
target_id: target_node_id,
target: None,
target,
emit_lint: &mut emit_lint,
},
attr_span,
@ -266,11 +261,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
&mut self,
attrs: &[ast::Attribute],
target_span: Span,
target_id: S::Id,
target: Target,
omit_doc: OmitDoc,
lower_span: impl Copy + Fn(Span) -> Span,
mut emit_lint: impl FnMut(AttributeLint<S::Id>),
mut emit_lint: impl FnMut(LintId, Span, AttributeLintKind),
) -> Vec<Attribute> {
let mut attributes = Vec::new();
let mut attr_paths: Vec<RefPathParser<'_>> = Vec::new();
@ -326,7 +320,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
lower_span(n.item.span()),
n.item.unsafety,
&mut emit_lint,
target_id,
);
let parts =
@ -378,8 +371,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
shared: SharedContext {
cx: self,
target_span,
target_id,
target: Some(target),
target,
emit_lint: &mut emit_lint,
},
attr_span,
@ -427,13 +419,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
early_parsed_state.finalize_early_parsed_attributes(&mut attributes);
for f in &S::parsers().finalizers {
if let Some(attr) = f(&mut FinalizeContext {
shared: SharedContext {
cx: self,
target_span,
target_id,
target: Some(target),
emit_lint: &mut emit_lint,
},
shared: SharedContext { cx: self, target_span, target, emit_lint: &mut emit_lint },
all_attrs: &attr_paths,
}) {
attributes.push(Attribute::Parsed(attr));

View file

@ -1,7 +1,7 @@
use rustc_ast::Safety;
use rustc_feature::{AttributeSafety, BUILTIN_ATTRIBUTE_MAP};
use rustc_hir::AttrPath;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::lints::AttributeLintKind;
use rustc_session::lint::LintId;
use rustc_session::lint::builtin::UNSAFE_ATTR_OUTSIDE_UNSAFE;
use rustc_span::Span;
@ -15,8 +15,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
attr_path: &AttrPath,
attr_span: Span,
attr_safety: Safety,
emit_lint: &mut impl FnMut(AttributeLint<S::Id>),
target_id: S::Id,
emit_lint: &mut impl FnMut(LintId, Span, AttributeLintKind),
) {
if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
return;
@ -82,16 +81,15 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
},
);
} else {
emit_lint(AttributeLint {
lint_id: LintId::of(UNSAFE_ATTR_OUTSIDE_UNSAFE),
id: target_id,
span: path_span,
kind: AttributeLintKind::UnsafeAttrOutsideUnsafe {
emit_lint(
LintId::of(UNSAFE_ATTR_OUTSIDE_UNSAFE),
path_span,
AttributeLintKind::UnsafeAttrOutsideUnsafe {
attribute_name_span: path_span,
sugg_spans: not_from_proc_macro
.then(|| (diag_span.shrink_to_lo(), diag_span.shrink_to_hi())),
},
})
)
}
}

View file

@ -10,8 +10,8 @@ use rustc_attr_parsing::{
AttributeParser, CFG_TEMPLATE, ParsedDescription, ShouldEmit, parse_cfg_entry,
};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
use rustc_hir::AttrPath;
use rustc_hir::attrs::CfgEntry;
use rustc_hir::{AttrPath, Target};
use rustc_parse::exp;
use rustc_span::{ErrorGuaranteed, Span, sym};
@ -52,6 +52,8 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
ParsedDescription::Macro,
span,
cx.current_expansion.lint_node_id,
// Doesn't matter what the target actually is here.
Target::Crate,
Some(cx.ecfg.features),
ShouldEmit::ErrorsAndLints,
&meta,

View file

@ -19,6 +19,7 @@ use rustc_feature::{
ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, REMOVED_LANG_FEATURES,
UNSTABLE_LANG_FEATURES,
};
use rustc_hir::Target;
use rustc_session::Session;
use rustc_session::parse::feature_err;
use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym};
@ -403,6 +404,8 @@ impl<'a> StripUnconfigured<'a> {
attr,
attr.span,
self.lint_node_id,
// Doesn't matter what the target actually is here.
Target::Crate,
self.features,
emit_errors,
parse_cfg,

View file

@ -2218,6 +2218,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
&attr,
attr.span,
self.cfg().lint_node_id,
// Target doesn't matter for `cfg` parsing.
Target::Crate,
self.cfg().features,
ShouldEmit::ErrorsAndLints,
parse_cfg,

View file

@ -148,11 +148,10 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
let attrs = parser.parse_attribute_list(
&i.attrs,
i.span,
i.id,
Target::MacroDef,
OmitDoc::Skip,
std::convert::identity,
|_l| {
|_lint_id, _span, _kind| {
// FIXME(jdonszelmann): emit lints here properly
// NOTE that before new attribute parsing, they didn't happen either
// but it would be nice if we could change that.