@@ -140,19 +140,17 @@ pub(crate) struct Attribute {
140
140
141
141
#[ derive( Clone , Copy , PartialEq ) ]
142
142
pub ( crate ) enum AttributeKind {
143
- // #[doc ...]
144
- Doc ,
145
- // #[inline ...]
146
- Inline ,
147
- Other ,
143
+ TraitOnly ,
144
+ ImplOnly ,
145
+ TraitAndImpl ,
148
146
}
149
147
150
148
impl Attribute {
151
149
pub ( crate ) fn new ( tokens : Vec < TokenTree > ) -> Self {
152
150
Self {
153
151
pound_token : Punct :: new ( '#' , Spacing :: Alone ) ,
154
152
tokens : Group :: new ( Delimiter :: Bracket , tokens. into_iter ( ) . collect ( ) ) ,
155
- kind : AttributeKind :: Other ,
153
+ kind : AttributeKind :: TraitAndImpl ,
156
154
}
157
155
}
158
156
}
@@ -311,15 +309,19 @@ pub(crate) struct TraitItemType {
311
309
pub ( crate ) mod parsing {
312
310
use std:: iter:: FromIterator ;
313
311
314
- use proc_macro:: { Delimiter , Punct , Spacing , TokenStream , TokenTree } ;
312
+ use proc_macro:: { Delimiter , Group , Punct , Spacing , TokenStream , TokenTree } ;
315
313
316
314
use super :: {
317
315
Attribute , AttributeKind , BoundLifetimes , ConstParam , FnArg , GenericParam , Generics ,
318
316
ImplItem , ImplItemConst , ImplItemMethod , ImplItemType , ItemImpl , Lifetime , LifetimeDef ,
319
317
PredicateLifetime , PredicateType , Signature , TypeParam , TypeParamBound , Visibility ,
320
318
WhereClause , WherePredicate ,
321
319
} ;
322
- use crate :: { error:: Result , iter:: TokenIter , to_tokens:: ToTokens } ;
320
+ use crate :: {
321
+ error:: { Error , Result } ,
322
+ iter:: TokenIter ,
323
+ to_tokens:: ToTokens ,
324
+ } ;
323
325
324
326
fn parse_until_punct ( input : & mut TokenIter , ch : char ) -> Result < ( Vec < TokenTree > , Punct ) > {
325
327
let mut buf = vec ! [ ] ;
@@ -388,27 +390,62 @@ pub(crate) mod parsing {
388
390
389
391
fn parse_attrs ( input : & mut TokenIter ) -> Result < Vec < Attribute > > {
390
392
let mut attrs = vec ! [ ] ;
393
+ let mut prev_kind_override: Option < ( AttributeKind , Group ) > = None ;
391
394
while input. peek_t ( & '#' ) {
392
395
let pound_token = input. parse_punct ( '#' ) ?;
393
396
let tokens = input. parse_group ( Delimiter :: Bracket ) ?;
394
- let mut kind = AttributeKind :: Other ;
397
+ let mut kind = AttributeKind :: TraitAndImpl ;
398
+ let mut cur_kind_override = None ;
395
399
let mut iter = TokenIter :: new ( tokens. stream ( ) ) ;
396
400
if let Some ( TokenTree :: Ident ( i) ) = iter. next ( ) {
397
401
match iter. next ( ) {
398
402
// ignore #[path ...]
399
403
Some ( TokenTree :: Punct ( ref p) ) if p. as_char ( ) == ':' => { }
400
- _ => match & * i. to_string ( ) {
401
- "doc" => kind = AttributeKind :: Doc ,
402
- "inline" => kind = AttributeKind :: Inline ,
404
+ next => match & * i. to_string ( ) {
405
+ "doc" => kind = AttributeKind :: TraitOnly ,
406
+ "inline" => kind = AttributeKind :: ImplOnly ,
407
+ "ext_attr" => match next. map ( |x| x. to_string ( ) ) . as_deref ( ) {
408
+ Some ( "(impl_only)" ) => {
409
+ cur_kind_override = Some ( AttributeKind :: ImplOnly ) ;
410
+ }
411
+ Some ( "(trait_only)" ) => {
412
+ cur_kind_override = Some ( AttributeKind :: TraitOnly ) ;
413
+ }
414
+ Some ( _) => {
415
+ return Err ( Error :: new ( & tokens, "invalid attribute tag" . into ( ) ) )
416
+ }
417
+ None => {
418
+ return Err ( Error :: new ( & tokens, "missing attribute tag" . into ( ) ) )
419
+ }
420
+ } ,
403
421
_ => { }
404
422
} ,
405
423
}
406
424
}
407
425
426
+ match ( prev_kind_override. take ( ) , cur_kind_override) {
427
+ ( Some ( ( prev_kind_override, _) ) , None ) => {
428
+ kind = prev_kind_override;
429
+ }
430
+ ( None , Some ( cur_kind_override) ) => {
431
+ prev_kind_override = Some ( ( cur_kind_override, tokens) ) ;
432
+ continue ;
433
+ }
434
+ ( Some ( _) , Some ( _) ) => {
435
+ return Err ( Error :: new ( & tokens, "repeated attribute tag" . into ( ) ) )
436
+ }
437
+ ( None , None ) => { }
438
+ }
439
+
408
440
let attr = Attribute { pound_token, tokens, kind } ;
409
441
attrs. push ( attr) ;
410
442
}
411
- Ok ( attrs)
443
+
444
+ if let Some ( ( _, tokens) ) = prev_kind_override {
445
+ Err ( Error :: new ( & tokens, "unused attribute tag" . into ( ) ) )
446
+ } else {
447
+ Ok ( attrs)
448
+ }
412
449
}
413
450
414
451
fn parse_generics ( input : & mut TokenIter ) -> Result < Generics > {
0 commit comments