@@ -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,29 @@ 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 (
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
+ }
699
734
}
700
735
701
736
impl < ' sess , S : Stage > AttributeParser < ' sess , S > {
@@ -712,6 +747,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
712
747
& self . sess
713
748
}
714
749
750
+ pub ( crate ) fn stage ( & self ) -> & S {
751
+ & self . stage
752
+ }
753
+
715
754
pub ( crate ) fn features ( & self ) -> & ' sess Features {
716
755
self . features . expect ( "features not available at this point in the compiler" )
717
756
}
@@ -785,12 +824,14 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
785
824
ast:: AttrKind :: Normal ( n) => {
786
825
attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
787
826
827
+ // Parse attribute using new infra
788
828
let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
789
829
let path = parser. path ( ) ;
790
830
let args = parser. args ( ) ;
791
831
let parts = path. segments ( ) . map ( |i| i. name ) . collect :: < Vec < _ > > ( ) ;
792
832
793
833
if let Some ( accepts) = S :: parsers ( ) . 0 . get ( parts. as_slice ( ) ) {
834
+ self . validate_attribute ( attr, target_id, & mut emit_lint, true ) ;
794
835
for ( template, accept) in accepts {
795
836
let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
796
837
shared : SharedContext {
@@ -821,7 +862,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
821
862
// // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
822
863
// "attribute {path} wasn't parsed and isn't a know tool attribute",
823
864
// );
824
-
865
+ self . validate_attribute ( attr , target_id , & mut emit_lint , false ) ;
825
866
attributes. push ( Attribute :: Unparsed ( Box :: new ( AttrItem {
826
867
path : AttrPath :: from_ast ( & n. item . path ) ,
827
868
args : self . lower_attr_args ( & n. item . args , lower_span) ,
0 commit comments