1
+ use std:: borrow:: Cow ;
2
+
1
3
use rustc_ast as ast;
2
4
use rustc_ast:: NodeId ;
3
5
use rustc_errors:: DiagCtxtHandle ;
@@ -49,27 +51,44 @@ impl<'sess> AttributeParser<'sess, Early> {
49
51
target_node_id : NodeId ,
50
52
features : Option < & ' sess Features > ,
51
53
) -> 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 (
56
55
sess,
57
- stage : Early { emit_errors : ShouldEmit :: Nothing } ,
58
- } ;
59
- let mut parsed = p. parse_attribute_list (
60
56
attrs,
57
+ Some ( sym) ,
58
+ Target :: Crate , // Does not matter, we're not going to emit errors anyways
61
59
target_span,
62
60
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,
64
85
OmitDoc :: Skip ,
65
86
std:: convert:: identity,
66
87
|_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)
68
90
} ,
69
- ) ;
70
- assert ! ( parsed. len( ) <= 1 ) ;
71
-
72
- parsed. pop ( )
91
+ )
73
92
}
74
93
75
94
pub fn parse_single < T > (
@@ -79,9 +98,9 @@ impl<'sess> AttributeParser<'sess, Early> {
79
98
target_node_id : NodeId ,
80
99
features : Option < & ' sess Features > ,
81
100
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 > ,
83
102
template : & AttributeTemplate ,
84
- ) -> T {
103
+ ) -> Option < T > {
85
104
let mut parser = Self {
86
105
features,
87
106
tools : Vec :: new ( ) ,
@@ -92,7 +111,9 @@ impl<'sess> AttributeParser<'sess, Early> {
92
111
let ast:: AttrKind :: Normal ( normal_attr) = & attr. kind else {
93
112
panic ! ( "parse_single called on a doc attr" )
94
113
} ;
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) ?;
96
117
let path = meta_parser. path ( ) ;
97
118
let args = meta_parser. args ( ) ;
98
119
let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
@@ -199,14 +220,22 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
199
220
// }))
200
221
// }
201
222
ast:: AttrKind :: Normal ( n) => {
202
- attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
223
+ attr_paths. push ( PathParser ( Cow :: Borrowed ( & n. item . path ) ) ) ;
203
224
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 < _ > > ( ) ;
208
227
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 ( ) ;
210
239
for accept in accepts {
211
240
let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
212
241
shared : SharedContext {
0 commit comments