make tools on AttributeParser hold reference to RegisteredTools

This commit is contained in:
Edvin Bryntesson
2026-03-04 11:06:15 +01:00
parent 8275de8cdd
commit 76fd1b3df3
7 changed files with 29 additions and 11 deletions
+1
View File
@@ -3586,6 +3586,7 @@ dependencies = [
"rustc_feature",
"rustc_hir",
"rustc_lexer",
"rustc_lint_defs",
"rustc_macros",
"rustc_parse",
"rustc_parse_format",
+1 -2
View File
@@ -164,7 +164,6 @@ struct LoweringContext<'a, 'hir> {
impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn new(tcx: TyCtxt<'hir>, resolver: &'a ResolverAstLowering<'hir>) -> Self {
let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect();
Self {
tcx,
resolver,
@@ -220,7 +219,7 @@ fn new(tcx: TyCtxt<'hir>, resolver: &'a ResolverAstLowering<'hir>) -> Self {
attribute_parser: AttributeParser::new(
tcx.sess,
tcx.features(),
registered_tools,
tcx.registered_tools(()),
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
),
delayed_lints: Vec::new(),
+1
View File
@@ -13,6 +13,7 @@ rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
rustc_hir = { path = "../rustc_hir" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
rustc_macros = { path = "../rustc_macros" }
rustc_parse = { path = "../rustc_parse" }
rustc_parse_format = { path = "../rustc_parse_format" }
@@ -265,10 +265,18 @@ fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
let span = self.span?;
let Some(tools) = cx.tools else {
unreachable!("tools required while parsing attributes");
};
// only if we found a naked attribute do we do the somewhat expensive check
'outer: for other_attr in cx.all_attrs {
for allowed_attr in ALLOW_LIST {
if other_attr.segments().next().is_some_and(|i| cx.tools.contains(&i.name)) {
if other_attr
.segments()
.next()
.is_some_and(|i| tools.iter().any(|tool| tool.name == i.name))
{
// effectively skips the error message being emitted below
// if it's a tool attribute
continue 'outer;
+15 -7
View File
@@ -8,6 +8,7 @@
use rustc_feature::{AttributeTemplate, Features};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
use rustc_lint_defs::RegisteredTools;
use rustc_session::Session;
use rustc_session::lint::LintId;
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
@@ -33,7 +34,7 @@ pub struct EmitAttribute(
/// Context created once, for example as part of the ast lowering
/// context, through which all attributes can be lowered.
pub struct AttributeParser<'sess> {
pub(crate) tools: Vec<Symbol>,
pub(crate) tools: Option<&'sess RegisteredTools>,
pub(crate) features: Option<&'sess Features>,
pub(crate) sess: &'sess Session,
pub(crate) should_emit: ShouldEmit,
@@ -59,6 +60,8 @@ impl<'sess> AttributeParser<'sess> {
/// No diagnostics will be emitted when parsing limited. Lints are not emitted at all, while
/// errors will be emitted as a delayed bugs. in other words, we *expect* attributes parsed
/// with `parse_limited` to be reparsed later during ast lowering where we *do* emit the errors
///
/// Due to this function not taking in RegisteredTools, *do not* use this for parsing any lint attributes
pub fn parse_limited(
sess: &'sess Session,
attrs: &[ast::Attribute],
@@ -79,6 +82,8 @@ pub fn parse_limited(
/// This does the same as `parse_limited`, except it has a `should_emit` parameter which allows it to emit errors.
/// Usually you want `parse_limited`, which emits no errors.
///
/// Due to this function not taking in RegisteredTools, *do not* use this for parsing any lint attributes
pub fn parse_limited_should_emit(
sess: &'sess Session,
attrs: &[ast::Attribute],
@@ -98,6 +103,7 @@ pub fn parse_limited_should_emit(
target_node_id,
features,
should_emit,
None,
);
assert!(parsed.len() <= 1);
parsed.pop()
@@ -119,8 +125,9 @@ pub fn parse_limited_all(
target_node_id: NodeId,
features: Option<&'sess Features>,
should_emit: ShouldEmit,
tools: Option<&'sess RegisteredTools>,
) -> Vec<Attribute> {
let mut p = Self { features, tools: Vec::new(), parse_only, sess, should_emit };
let mut p = Self { features, tools, parse_only, sess, should_emit };
p.parse_attribute_list(
attrs,
target_span,
@@ -202,7 +209,7 @@ pub fn parse_single_args<T, I>(
parse_fn: fn(cx: &mut AcceptContext<'_, '_>, item: &I) -> T,
template: &AttributeTemplate,
) -> T {
let mut parser = Self { features, tools: Vec::new(), parse_only: None, sess, should_emit };
let mut parser = Self { features, tools: None, parse_only: None, sess, should_emit };
let mut emit_lint = |lint_id: LintId, span: MultiSpan, kind: EmitAttribute| {
sess.psess.dyn_buffer_lint_sess(lint_id.lint, span, target_node_id, kind.0)
};
@@ -237,10 +244,10 @@ impl<'sess> AttributeParser<'sess> {
pub fn new(
sess: &'sess Session,
features: &'sess Features,
tools: Vec<Symbol>,
tools: &'sess RegisteredTools,
should_emit: ShouldEmit,
) -> Self {
Self { features: Some(features), tools, parse_only: None, sess, should_emit }
Self { features: Some(features), tools: Some(tools), parse_only: None, sess, should_emit }
}
pub(crate) fn sess(&self) -> &'sess Session {
@@ -432,12 +439,13 @@ pub fn parse_attribute_list(
let attr = Attribute::Unparsed(Box::new(attr));
if self.tools.contains(&parts[0])
if self.tools.is_some_and(|tools| {
tools.iter().any(|tool| tool.name == parts[0])
// FIXME: this can be removed once #152369 has been merged.
// https://github.com/rust-lang/rust/pull/152369
|| [sym::allow, sym::deny, sym::expect, sym::forbid, sym::warn]
.contains(&parts[0])
{
}) {
attributes.push(attr);
} else {
dropped_attributes.push(attr);
+1
View File
@@ -2250,6 +2250,7 @@ fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
self.cx.current_expansion.lint_node_id,
Some(self.cx.ecfg.features),
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
Some(self.cx.resolver.registered_tools()),
);
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
+1 -1
View File
@@ -149,7 +149,7 @@ fn visit_item(&mut self, i: &'a Item) {
let mut parser = AttributeParser::new(
&self.r.tcx.sess,
self.r.tcx.features(),
Vec::new(),
self.r.tcx().registered_tools(()),
ShouldEmit::Nothing,
);
let attrs = parser.parse_attribute_list(