@@ -203,10 +203,11 @@ mod private {
203
203
#[ allow( private_interfaces) ]
204
204
pub trait Stage : Sized + ' static + Sealed {
205
205
type Id : Copy ;
206
- const SHOULD_EMIT_LINTS : bool ;
207
206
208
207
fn parsers ( ) -> & ' static group_type ! ( Self ) ;
209
208
209
+ fn should_emit_errors_and_lints ( & self ) -> bool ;
210
+
210
211
fn emit_err < ' sess > (
211
212
& self ,
212
213
sess : & ' sess Session ,
@@ -218,11 +219,15 @@ pub trait Stage: Sized + 'static + Sealed {
218
219
#[ allow( private_interfaces) ]
219
220
impl Stage for Early {
220
221
type Id = NodeId ;
221
- const SHOULD_EMIT_LINTS : bool = false ;
222
222
223
223
fn parsers ( ) -> & ' static group_type ! ( Self ) {
224
224
& early:: ATTRIBUTE_PARSERS
225
225
}
226
+
227
+ fn should_emit_errors_and_lints ( & self ) -> bool {
228
+ self . emit_errors . should_emit ( )
229
+ }
230
+
226
231
fn emit_err < ' sess > (
227
232
& self ,
228
233
sess : & ' sess Session ,
@@ -240,11 +245,15 @@ impl Stage for Early {
240
245
#[ allow( private_interfaces) ]
241
246
impl Stage for Late {
242
247
type Id = HirId ;
243
- const SHOULD_EMIT_LINTS : bool = true ;
244
248
245
249
fn parsers ( ) -> & ' static group_type ! ( Self ) {
246
250
& late:: ATTRIBUTE_PARSERS
247
251
}
252
+
253
+ fn should_emit_errors_and_lints ( & self ) -> bool {
254
+ true
255
+ }
256
+
248
257
fn emit_err < ' sess > (
249
258
& self ,
250
259
tcx : & ' sess Session ,
@@ -290,7 +299,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
290
299
/// must be delayed until after HIR is built. This method will take care of the details of
291
300
/// that.
292
301
pub ( crate ) fn emit_lint ( & mut self , lint : AttributeLintKind , span : Span ) {
293
- if !S :: SHOULD_EMIT_LINTS {
302
+ if !self . stage . should_emit_errors_and_lints ( ) {
294
303
return ;
295
304
}
296
305
let id = self . target_id ;
@@ -696,6 +705,22 @@ impl<'sess> AttributeParser<'sess, Early> {
696
705
} ;
697
706
parse_fn ( & mut cx, args)
698
707
}
708
+
709
+ /// Returns whether the attribute is valid
710
+ pub fn validate_attribute_early (
711
+ sess : & ' sess Session ,
712
+ attr : & ast:: Attribute ,
713
+ target_node_id : NodeId ,
714
+ ) -> bool {
715
+ let parser = Self {
716
+ features : None ,
717
+ tools : Vec :: new ( ) ,
718
+ parse_only : None ,
719
+ sess,
720
+ stage : Early { emit_errors : ShouldEmit :: ErrorsAndLints } ,
721
+ } ;
722
+ parser. validate_attribute ( attr, target_node_id, & mut |_| { } , true )
723
+ }
699
724
}
700
725
701
726
impl < ' sess , S : Stage > AttributeParser < ' sess , S > {
@@ -712,6 +737,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
712
737
& self . sess
713
738
}
714
739
740
+ pub ( crate ) fn stage ( & self ) -> & S {
741
+ & self . stage
742
+ }
743
+
715
744
pub ( crate ) fn features ( & self ) -> & ' sess Features {
716
745
self . features . expect ( "features not available at this point in the compiler" )
717
746
}
@@ -785,12 +814,14 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
785
814
ast:: AttrKind :: Normal ( n) => {
786
815
attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
787
816
817
+ // Parse attribute using new infra
788
818
let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
789
819
let path = parser. path ( ) ;
790
820
let args = parser. args ( ) ;
791
821
let parts = path. segments ( ) . map ( |i| i. name ) . collect :: < Vec < _ > > ( ) ;
792
822
793
823
if let Some ( accepts) = S :: parsers ( ) . 0 . get ( parts. as_slice ( ) ) {
824
+ self . validate_attribute ( attr, target_id, & mut emit_lint, true ) ;
794
825
for ( template, accept) in accepts {
795
826
let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
796
827
shared : SharedContext {
@@ -821,7 +852,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
821
852
// // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
822
853
// "attribute {path} wasn't parsed and isn't a know tool attribute",
823
854
// );
824
-
855
+ self . validate_attribute ( attr , target_id , & mut emit_lint , false ) ;
825
856
attributes. push ( Attribute :: Unparsed ( Box :: new ( AttrItem {
826
857
path : AttrPath :: from_ast ( & n. item . path ) ,
827
858
args : self . lower_attr_args ( & n. item . args , lower_span) ,
0 commit comments