1+ use std:: borrow:: Cow ;
2+
13use rustc_ast as ast;
24use rustc_ast:: NodeId ;
35use rustc_errors:: DiagCtxtHandle ;
@@ -49,27 +51,44 @@ impl<'sess> AttributeParser<'sess, Early> {
4951 target_node_id : NodeId ,
5052 features : Option < & ' sess Features > ,
5153 ) -> Option < Attribute > {
52- let mut p = Self {
53- features,
54- tools : Vec :: new ( ) ,
55- parse_only : Some ( sym) ,
54+ let mut parsed = Self :: parse_limited_all (
5655 sess,
57- stage : Early { emit_errors : ShouldEmit :: Nothing } ,
58- } ;
59- let mut parsed = p. parse_attribute_list (
6056 attrs,
57+ Some ( sym) ,
58+ Target :: Crate , // Does not matter, we're not going to emit errors anyways
6159 target_span,
6260 target_node_id,
63- Target :: Crate , // Does not matter, we're not going to emit errors anyways
61+ features,
62+ ShouldEmit :: Nothing ,
63+ ) ;
64+ assert ! ( parsed. len( ) <= 1 ) ;
65+ parsed. pop ( )
66+ }
67+
68+ pub fn parse_limited_all (
69+ sess : & ' sess Session ,
70+ attrs : & [ ast:: Attribute ] ,
71+ parse_only : Option < Symbol > ,
72+ target : Target ,
73+ target_span : Span ,
74+ target_node_id : NodeId ,
75+ features : Option < & ' sess Features > ,
76+ emit_errors : ShouldEmit ,
77+ ) -> Vec < Attribute > {
78+ let mut p =
79+ Self { features, tools : Vec :: new ( ) , parse_only, sess, stage : Early { emit_errors } } ;
80+ p. parse_attribute_list (
81+ attrs,
82+ target_span,
83+ target_node_id,
84+ target,
6485 OmitDoc :: Skip ,
6586 std:: convert:: identity,
6687 |_lint| {
67- panic ! ( "can't emit lints here for now (nothing uses this atm)" ) ;
88+ // FIXME: Can't emit lints here for now
89+ // This branch can be hit when an attribute produces a warning during early parsing (such as attributes on macro calls)
6890 } ,
69- ) ;
70- assert ! ( parsed. len( ) <= 1 ) ;
71-
72- parsed. pop ( )
91+ )
7392 }
7493
7594 pub fn parse_single < T > (
@@ -79,9 +98,9 @@ impl<'sess> AttributeParser<'sess, Early> {
7998 target_node_id : NodeId ,
8099 features : Option < & ' sess Features > ,
81100 emit_errors : ShouldEmit ,
82- parse_fn : fn ( cx : & mut AcceptContext < ' _ , ' _ , Early > , item : & ArgParser < ' _ > ) -> T ,
101+ parse_fn : fn ( cx : & mut AcceptContext < ' _ , ' _ , Early > , item : & ArgParser < ' _ > ) -> Option < T > ,
83102 template : & AttributeTemplate ,
84- ) -> T {
103+ ) -> Option < T > {
85104 let mut parser = Self {
86105 features,
87106 tools : Vec :: new ( ) ,
@@ -92,7 +111,9 @@ impl<'sess> AttributeParser<'sess, Early> {
92111 let ast:: AttrKind :: Normal ( normal_attr) = & attr. kind else {
93112 panic ! ( "parse_single called on a doc attr" )
94113 } ;
95- let meta_parser = MetaItemParser :: from_attr ( normal_attr, parser. dcx ( ) ) ;
114+ let parts =
115+ normal_attr. item . path . segments . iter ( ) . map ( |seg| seg. ident . name ) . collect :: < Vec < _ > > ( ) ;
116+ let meta_parser = MetaItemParser :: from_attr ( normal_attr, & parts, & sess. psess , emit_errors) ?;
96117 let path = meta_parser. path ( ) ;
97118 let args = meta_parser. args ( ) ;
98119 let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
@@ -199,14 +220,22 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
199220 // }))
200221 // }
201222 ast:: AttrKind :: Normal ( n) => {
202- attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
223+ attr_paths. push ( PathParser ( Cow :: Borrowed ( & n. item . path ) ) ) ;
203224
204- let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
205- let path = parser. path ( ) ;
206- let args = parser. args ( ) ;
207- let path_parts = path. segments ( ) . map ( |i| i. name ) . collect :: < Vec < _ > > ( ) ;
225+ let parts =
226+ n. item . path . segments . iter ( ) . map ( |seg| seg. ident . name ) . collect :: < Vec < _ > > ( ) ;
208227
209- if let Some ( accepts) = S :: parsers ( ) . accepters . get ( path_parts. as_slice ( ) ) {
228+ if let Some ( accepts) = S :: parsers ( ) . accepters . get ( parts. as_slice ( ) ) {
229+ let Some ( parser) = MetaItemParser :: from_attr (
230+ n,
231+ & parts,
232+ & self . sess . psess ,
233+ self . stage . should_emit ( ) ,
234+ ) else {
235+ continue ;
236+ } ;
237+ let path = parser. path ( ) ;
238+ let args = parser. args ( ) ;
210239 for accept in accepts {
211240 let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
212241 shared : SharedContext {
0 commit comments