1+ use std:: borrow:: Cow ;
12use std:: cell:: RefCell ;
23use std:: collections:: BTreeMap ;
34use std:: ops:: { Deref , DerefMut } ;
@@ -213,7 +214,6 @@ mod private {
213214#[ allow( private_interfaces) ]
214215pub trait Stage : Sized + ' static + Sealed {
215216 type Id : Copy ;
216- const SHOULD_EMIT_LINTS : bool ;
217217
218218 fn parsers ( ) -> & ' static group_type ! ( Self ) ;
219219
@@ -222,13 +222,14 @@ pub trait Stage: Sized + 'static + Sealed {
222222 sess : & ' sess Session ,
223223 diag : impl for < ' x > Diagnostic < ' x > ,
224224 ) -> ErrorGuaranteed ;
225+
226+ fn should_emit ( & self ) -> ShouldEmit ;
225227}
226228
227229// allow because it's a sealed trait
228230#[ allow( private_interfaces) ]
229231impl Stage for Early {
230232 type Id = NodeId ;
231- const SHOULD_EMIT_LINTS : bool = false ;
232233
233234 fn parsers ( ) -> & ' static group_type ! ( Self ) {
234235 & early:: ATTRIBUTE_PARSERS
@@ -244,13 +245,16 @@ impl Stage for Early {
244245 sess. dcx ( ) . create_err ( diag) . delay_as_bug ( )
245246 }
246247 }
248+
249+ fn should_emit ( & self ) -> ShouldEmit {
250+ self . emit_errors
251+ }
247252}
248253
249254// allow because it's a sealed trait
250255#[ allow( private_interfaces) ]
251256impl Stage for Late {
252257 type Id = HirId ;
253- const SHOULD_EMIT_LINTS : bool = true ;
254258
255259 fn parsers ( ) -> & ' static group_type ! ( Self ) {
256260 & late:: ATTRIBUTE_PARSERS
@@ -262,6 +266,10 @@ impl Stage for Late {
262266 ) -> ErrorGuaranteed {
263267 tcx. dcx ( ) . emit_err ( diag)
264268 }
269+
270+ fn should_emit ( & self ) -> ShouldEmit {
271+ ShouldEmit :: ErrorsAndLints
272+ }
265273}
266274
267275/// used when parsing attributes for miscellaneous things *before* ast lowering
@@ -300,7 +308,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
300308 /// must be delayed until after HIR is built. This method will take care of the details of
301309 /// that.
302310 pub ( crate ) fn emit_lint ( & mut self , lint : AttributeLintKind , span : Span ) {
303- if !S :: SHOULD_EMIT_LINTS {
311+ if !self . stage . should_emit ( ) . should_emit ( ) {
304312 return ;
305313 }
306314 let id = self . target_id ;
@@ -657,14 +665,31 @@ impl<'sess> AttributeParser<'sess, Early> {
657665 target_node_id : NodeId ,
658666 features : Option < & ' sess Features > ,
659667 ) -> Option < Attribute > {
660- let mut p = Self {
661- features,
662- tools : Vec :: new ( ) ,
663- parse_only : Some ( sym) ,
668+ let mut parsed = Self :: parse_limited_all (
664669 sess,
665- stage : Early { emit_errors : ShouldEmit :: Nothing } ,
666- } ;
667- let mut parsed = p. parse_attribute_list (
670+ attrs,
671+ Some ( sym) ,
672+ target_span,
673+ target_node_id,
674+ features,
675+ ShouldEmit :: Nothing ,
676+ ) ;
677+ assert ! ( parsed. len( ) <= 1 ) ;
678+ parsed. pop ( )
679+ }
680+
681+ pub fn parse_limited_all (
682+ sess : & ' sess Session ,
683+ attrs : & [ ast:: Attribute ] ,
684+ parse_only : Option < Symbol > ,
685+ target_span : Span ,
686+ target_node_id : NodeId ,
687+ features : Option < & ' sess Features > ,
688+ emit_errors : ShouldEmit ,
689+ ) -> Vec < Attribute > {
690+ let mut p =
691+ Self { features, tools : Vec :: new ( ) , parse_only, sess, stage : Early { emit_errors } } ;
692+ p. parse_attribute_list (
668693 attrs,
669694 target_span,
670695 target_node_id,
@@ -673,10 +698,7 @@ impl<'sess> AttributeParser<'sess, Early> {
673698 |_lint| {
674699 panic ! ( "can't emit lints here for now (nothing uses this atm)" ) ;
675700 } ,
676- ) ;
677- assert ! ( parsed. len( ) <= 1 ) ;
678-
679- parsed. pop ( )
701+ )
680702 }
681703
682704 pub fn parse_single < T > (
@@ -686,9 +708,9 @@ impl<'sess> AttributeParser<'sess, Early> {
686708 target_node_id : NodeId ,
687709 features : Option < & ' sess Features > ,
688710 emit_errors : ShouldEmit ,
689- parse_fn : fn ( cx : & mut AcceptContext < ' _ , ' _ , Early > , item : & ArgParser < ' _ > ) -> T ,
711+ parse_fn : fn ( cx : & mut AcceptContext < ' _ , ' _ , Early > , item : & ArgParser < ' _ > ) -> Option < T > ,
690712 template : & AttributeTemplate ,
691- ) -> T {
713+ ) -> Option < T > {
692714 let mut parser = Self {
693715 features,
694716 tools : Vec :: new ( ) ,
@@ -699,7 +721,7 @@ impl<'sess> AttributeParser<'sess, Early> {
699721 let ast:: AttrKind :: Normal ( normal_attr) = & attr. kind else {
700722 panic ! ( "parse_single called on a doc attr" )
701723 } ;
702- let meta_parser = MetaItemParser :: from_attr ( normal_attr, parser . dcx ( ) ) ;
724+ let meta_parser = MetaItemParser :: from_attr ( normal_attr, & sess . psess , emit_errors ) ? ;
703725 let path = meta_parser. path ( ) ;
704726 let args = meta_parser. args ( ) ;
705727 let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
@@ -804,14 +826,22 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
804826 // }))
805827 // }
806828 ast:: AttrKind :: Normal ( n) => {
807- attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
829+ attr_paths. push ( PathParser ( Cow :: Borrowed ( & n. item . path ) ) ) ;
808830
809- let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
810- let path = parser. path ( ) ;
811- let args = parser. args ( ) ;
812- let parts = path. segments ( ) . map ( |i| i. name ) . collect :: < Vec < _ > > ( ) ;
831+ let parts =
832+ n. item . path . segments . iter ( ) . map ( |seg| seg. ident . name ) . collect :: < Vec < _ > > ( ) ;
813833
814834 if let Some ( accepts) = S :: parsers ( ) . 0 . get ( parts. as_slice ( ) ) {
835+ let Some ( parser) = MetaItemParser :: from_attr (
836+ n,
837+ & self . sess . psess ,
838+ self . stage . should_emit ( ) ,
839+ ) else {
840+ continue ;
841+ } ;
842+ let path = parser. path ( ) ;
843+ let args = parser. args ( ) ;
844+
815845 for ( template, accept) in accepts {
816846 let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
817847 shared : SharedContext {
0 commit comments