diff options
| author | Jonathan Brouwer <jonathantbrouwer@gmail.com> | 2025-07-31 15:38:08 +0200 |
|---|---|---|
| committer | Jonathan Brouwer <jonathantbrouwer@gmail.com> | 2025-08-22 08:58:45 +0200 |
| commit | 17e34f6b2418975a360755a1e1a3b8793864da9b (patch) | |
| tree | 63f0e2d2f543cee219d18f565b0ba445b550899b | |
| parent | 549314bdb7b7a3ac1313feea9283366f5115fca7 (diff) | |
| download | rust-17e34f6b2418975a360755a1e1a3b8793864da9b.tar.gz rust-17e34f6b2418975a360755a1e1a3b8793864da9b.zip | |
Use the new attribute parser throughout the codebase
| -rw-r--r-- | compiler/rustc_attr_parsing/src/interface.rs | 73 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/src/validate_attr.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/config.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/expand.rs | 21 |
4 files changed, 71 insertions, 41 deletions
diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 22bbea766f2..f652d39a708 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use rustc_ast as ast; use rustc_ast::NodeId; use rustc_errors::DiagCtxtHandle; @@ -49,27 +51,44 @@ impl<'sess> AttributeParser<'sess, Early> { target_node_id: NodeId, features: Option<&'sess Features>, ) -> Option<Attribute> { - let mut p = Self { - features, - tools: Vec::new(), - parse_only: Some(sym), + let mut parsed = Self::parse_limited_all( sess, - stage: Early { emit_errors: ShouldEmit::Nothing }, - }; - let mut parsed = p.parse_attribute_list( attrs, + Some(sym), + Target::Crate, // Does not matter, we're not going to emit errors anyways target_span, target_node_id, - Target::Crate, // Does not matter, we're not going to emit errors anyways + features, + ShouldEmit::Nothing, + ); + assert!(parsed.len() <= 1); + parsed.pop() + } + + pub fn parse_limited_all( + sess: &'sess Session, + attrs: &[ast::Attribute], + parse_only: Option<Symbol>, + target: Target, + target_span: Span, + target_node_id: NodeId, + features: Option<&'sess Features>, + emit_errors: ShouldEmit, + ) -> Vec<Attribute> { + let mut p = + Self { features, tools: Vec::new(), parse_only, sess, stage: Early { emit_errors } }; + p.parse_attribute_list( + attrs, + target_span, + target_node_id, + target, OmitDoc::Skip, std::convert::identity, |_lint| { - panic!("can't emit lints here for now (nothing uses this atm)"); + // FIXME: Can't emit lints here for now + // This branch can be hit when an attribute produces a warning during early parsing (such as attributes on macro calls) }, - ); - assert!(parsed.len() <= 1); - - parsed.pop() + ) } pub fn parse_single<T>( @@ -79,9 +98,9 @@ impl<'sess> AttributeParser<'sess, Early> { target_node_id: NodeId, features: Option<&'sess Features>, emit_errors: ShouldEmit, - parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T, + parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> Option<T>, template: &AttributeTemplate, - ) -> T { + ) -> Option<T> { let mut parser = Self { features, tools: Vec::new(), @@ -92,7 +111,9 @@ impl<'sess> AttributeParser<'sess, Early> { let ast::AttrKind::Normal(normal_attr) = &attr.kind else { panic!("parse_single called on a doc attr") }; - let meta_parser = MetaItemParser::from_attr(normal_attr, parser.dcx()); + let parts = + normal_attr.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>(); + let meta_parser = MetaItemParser::from_attr(normal_attr, &parts, &sess.psess, emit_errors)?; let path = meta_parser.path(); let args = meta_parser.args(); let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext { @@ -199,14 +220,22 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { // })) // } ast::AttrKind::Normal(n) => { - attr_paths.push(PathParser::Ast(&n.item.path)); + attr_paths.push(PathParser(Cow::Borrowed(&n.item.path))); - let parser = MetaItemParser::from_attr(n, self.dcx()); - let path = parser.path(); - let args = parser.args(); - let path_parts = path.segments().map(|i| i.name).collect::<Vec<_>>(); + let parts = + n.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>(); - if let Some(accepts) = S::parsers().accepters.get(path_parts.as_slice()) { + if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) { + let Some(parser) = MetaItemParser::from_attr( + n, + &parts, + &self.sess.psess, + self.stage.should_emit(), + ) else { + continue; + }; + let path = parser.path(); + let args = parser.args(); for accept in accepts { let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { shared: SharedContext { diff --git a/compiler/rustc_attr_parsing/src/validate_attr.rs b/compiler/rustc_attr_parsing/src/validate_attr.rs index da3a1cbe016..7a7624893bd 100644 --- a/compiler/rustc_attr_parsing/src/validate_attr.rs +++ b/compiler/rustc_attr_parsing/src/validate_attr.rs @@ -33,7 +33,10 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute, id: NodeId) { // Check input tokens for built-in and key-value attributes. match builtin_attr_info { // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. - Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => { + Some(BuiltinAttribute { name, template, .. }) => { + if AttributeParser::<Late>::is_parsed_attribute(slice::from_ref(&name)) { + return; + } match parse_meta(psess, attr) { // Don't check safety again, we just did that Ok(meta) => { @@ -259,9 +262,6 @@ pub fn check_builtin_meta_item( ) { if !is_attr_template_compatible(&template, &meta.kind) { // attrs with new parsers are locally validated so excluded here - if AttributeParser::<Late>::is_parsed_attribute(slice::from_ref(&name)) { - return; - } emit_malformed_attribute(psess, style, meta.span, name, template); } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index db5b45ff3d5..15419ab7423 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -415,16 +415,6 @@ impl<'a> StripUnconfigured<'a> { node: NodeId, emit_errors: ShouldEmit, ) -> EvalConfigResult { - // We need to run this to do basic validation of the attribute, such as that lits are valid, etc - // FIXME(jdonszelmann) this should not be necessary in the future - match validate_attr::parse_meta(&self.sess.psess, attr) { - Ok(_) => {} - Err(err) => { - err.emit(); - return EvalConfigResult::True; - } - } - // Unsafety check needs to be done explicitly here because this attribute will be removed before the normal check deny_builtin_meta_unsafety( self.sess.dcx(), diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 7bc380f0939..1c71f9a9be1 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1,21 +1,22 @@ use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; -use std::{iter, mem}; +use std::{iter, mem, slice}; use rustc_ast::mut_visit::*; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list}; use rustc_ast::{ - self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, DUMMY_NODE_ID, - ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, - MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token, + self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, CRATE_NODE_ID, + DUMMY_NODE_ID, ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, + MetaItemInner, MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token, }; use rustc_ast_pretty::pprust; -use rustc_attr_parsing::{EvalConfigResult, ShouldEmit, validate_attr}; +use rustc_attr_parsing::{AttributeParser, EvalConfigResult, ShouldEmit, validate_attr}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_errors::PResult; use rustc_feature::Features; +use rustc_hir::Target; use rustc_hir::def::MacroKinds; use rustc_parse::parser::{ AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma, @@ -2157,6 +2158,16 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { attr, self.cx.current_expansion.lint_node_id, ); + AttributeParser::parse_limited_all( + self.cx.sess, + slice::from_ref(attr), + None, + Target::MacroCall, + call.span(), + CRATE_NODE_ID, + Some(self.cx.ecfg.features), + ShouldEmit::ErrorsAndLints, + ); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; span = Some(current_span); |
