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