@@ -203,10 +203,12 @@ mod private {
203203#[ allow( private_interfaces) ]
204204pub trait Stage : Sized + ' static + Sealed {
205205 type Id : Copy ;
206- const SHOULD_EMIT_LINTS : bool ;
206+ const IS_LATE : bool ;
207207
208208 fn parsers ( ) -> & ' static group_type ! ( Self ) ;
209209
210+ fn should_emit_errors ( & self ) -> bool ;
211+
210212 fn emit_err < ' sess > (
211213 & self ,
212214 sess : & ' sess Session ,
@@ -218,11 +220,16 @@ pub trait Stage: Sized + 'static + Sealed {
218220#[ allow( private_interfaces) ]
219221impl Stage for Early {
220222 type Id = NodeId ;
221- const SHOULD_EMIT_LINTS : bool = false ;
223+ const IS_LATE : bool = false ;
222224
223225 fn parsers ( ) -> & ' static group_type ! ( Self ) {
224226 & early:: ATTRIBUTE_PARSERS
225227 }
228+
229+ fn should_emit_errors ( & self ) -> bool {
230+ self . emit_errors . should_emit ( )
231+ }
232+
226233 fn emit_err < ' sess > (
227234 & self ,
228235 sess : & ' sess Session ,
@@ -240,11 +247,16 @@ impl Stage for Early {
240247#[ allow( private_interfaces) ]
241248impl Stage for Late {
242249 type Id = HirId ;
243- const SHOULD_EMIT_LINTS : bool = true ;
250+ const IS_LATE : bool = true ;
244251
245252 fn parsers ( ) -> & ' static group_type ! ( Self ) {
246253 & late:: ATTRIBUTE_PARSERS
247254 }
255+
256+ fn should_emit_errors ( & self ) -> bool {
257+ true
258+ }
259+
248260 fn emit_err < ' sess > (
249261 & self ,
250262 tcx : & ' sess Session ,
@@ -290,7 +302,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
290302 /// must be delayed until after HIR is built. This method will take care of the details of
291303 /// that.
292304 pub ( crate ) fn emit_lint ( & mut self , lint : AttributeLintKind , span : Span ) {
293- if !S :: SHOULD_EMIT_LINTS {
305+ if !S :: IS_LATE {
294306 return ;
295307 }
296308 let id = self . target_id ;
@@ -696,6 +708,29 @@ impl<'sess> AttributeParser<'sess, Early> {
696708 } ;
697709 parse_fn ( & mut cx, args)
698710 }
711+
712+ /// Returns whether the attribute is valid
713+ pub fn validate_attribute_early (
714+ sess : & ' sess Session ,
715+ attr : & ast:: Attribute ,
716+ target_node_id : NodeId ,
717+ ) -> bool {
718+ let parser = Self {
719+ features : None ,
720+ tools : Vec :: new ( ) ,
721+ parse_only : None ,
722+ sess,
723+ stage : Early { emit_errors : ShouldEmit :: ErrorsAndLints } ,
724+ } ;
725+ parser. validate_attribute (
726+ attr,
727+ target_node_id,
728+ & mut |_lint| {
729+ panic ! ( "can't emit lints here for now (nothing uses this atm)" ) ;
730+ } ,
731+ true ,
732+ )
733+ }
699734}
700735
701736impl < ' sess , S : Stage > AttributeParser < ' sess , S > {
@@ -712,6 +747,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
712747 & self . sess
713748 }
714749
750+ pub ( crate ) fn stage ( & self ) -> & S {
751+ & self . stage
752+ }
753+
715754 pub ( crate ) fn features ( & self ) -> & ' sess Features {
716755 self . features . expect ( "features not available at this point in the compiler" )
717756 }
@@ -785,12 +824,14 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
785824 ast:: AttrKind :: Normal ( n) => {
786825 attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
787826
827+ // Parse attribute using new infra
788828 let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
789829 let path = parser. path ( ) ;
790830 let args = parser. args ( ) ;
791831 let parts = path. segments ( ) . map ( |i| i. name ) . collect :: < Vec < _ > > ( ) ;
792832
793833 if let Some ( accepts) = S :: parsers ( ) . 0 . get ( parts. as_slice ( ) ) {
834+ self . validate_attribute ( attr, target_id, & mut emit_lint, true ) ;
794835 for ( template, accept) in accepts {
795836 let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
796837 shared : SharedContext {
@@ -821,7 +862,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
821862 // // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
822863 // "attribute {path} wasn't parsed and isn't a know tool attribute",
823864 // );
824-
865+ self . validate_attribute ( attr , target_id , & mut emit_lint , false ) ;
825866 attributes. push ( Attribute :: Unparsed ( Box :: new ( AttrItem {
826867 path : AttrPath :: from_ast ( & n. item . path ) ,
827868 args : self . lower_attr_args ( & n. item . args , lower_span) ,
0 commit comments