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 ;
@@ -686,9 +694,9 @@ impl<'sess> AttributeParser<'sess, Early> {
686694 target_node_id : NodeId ,
687695 features : Option < & ' sess Features > ,
688696 emit_errors : ShouldEmit ,
689- parse_fn : fn ( cx : & mut AcceptContext < ' _ , ' _ , Early > , item : & ArgParser < ' _ > ) -> T ,
697+ parse_fn : fn ( cx : & mut AcceptContext < ' _ , ' _ , Early > , item : & ArgParser < ' _ > ) -> Option < T > ,
690698 template : & AttributeTemplate ,
691- ) -> T {
699+ ) -> Option < T > {
692700 let mut parser = Self {
693701 features,
694702 tools : Vec :: new ( ) ,
@@ -699,7 +707,7 @@ impl<'sess> AttributeParser<'sess, Early> {
699707 let ast:: AttrKind :: Normal ( normal_attr) = & attr. kind else {
700708 panic ! ( "parse_single called on a doc attr" )
701709 } ;
702- let meta_parser = MetaItemParser :: from_attr ( normal_attr, parser . dcx ( ) ) ;
710+ let meta_parser = MetaItemParser :: from_attr ( normal_attr, & sess . psess , emit_errors ) ? ;
703711 let path = meta_parser. path ( ) ;
704712 let args = meta_parser. args ( ) ;
705713 let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
@@ -804,14 +812,22 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
804812 // }))
805813 // }
806814 ast:: AttrKind :: Normal ( n) => {
807- attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
815+ attr_paths. push ( PathParser ( Cow :: Borrowed ( & n. item . path ) ) ) ;
808816
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 < _ > > ( ) ;
817+ let parts =
818+ n. item . path . segments . iter ( ) . map ( |seg| seg. ident . name ) . collect :: < Vec < _ > > ( ) ;
813819
814820 if let Some ( accepts) = S :: parsers ( ) . 0 . get ( parts. as_slice ( ) ) {
821+ let Some ( parser) = MetaItemParser :: from_attr (
822+ n,
823+ & self . sess . psess ,
824+ self . stage . should_emit ( ) ,
825+ ) else {
826+ continue ;
827+ } ;
828+ let path = parser. path ( ) ;
829+ let args = parser. args ( ) ;
830+
815831 for ( template, accept) in accepts {
816832 let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
817833 shared : SharedContext {
0 commit comments