@@ -269,6 +269,11 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
269269 mut emit_lint : impl FnMut ( LintId , Span , AttributeLintKind ) ,
270270 ) -> Vec < Attribute > {
271271 let mut attributes = Vec :: new ( ) ;
272+ // We store the attributes we intend to discard at the end of this function in order to
273+ // check they are applied to the right target and error out if necessary. In practice, we
274+ // end up dropping only derive attributes and derive helpers, both being fully processed
275+ // at macro expansion.
276+ let mut dropped_attributes = Vec :: new ( ) ;
272277 let mut attr_paths: Vec < RefPathParser < ' _ > > = Vec :: new ( ) ;
273278 let mut early_parsed_state = EarlyParsedState :: default ( ) ;
274279
@@ -304,7 +309,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
304309 kind : DocFragmentKind :: Sugared ( * comment_kind) ,
305310 span : attr_span,
306311 comment : * symbol,
307- } ) )
312+ } ) ) ;
308313 }
309314 ast:: AttrKind :: Normal ( n) => {
310315 attr_paths. push ( PathParser ( & n. item . path ) ) ;
@@ -393,29 +398,33 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
393398 Self :: check_target ( & accept. allowed_targets , target, & mut cx) ;
394399 }
395400 } else {
396- // If we're here, we must be compiling a tool attribute... Or someone
397- // forgot to parse their fancy new attribute. Let's warn them in any case.
398- // If you are that person, and you really think your attribute should
399- // remain unparsed, carefully read the documentation in this module and if
400- // you still think so you can add an exception to this assertion.
401-
402- // FIXME(jdonszelmann): convert other attributes, and check with this that
403- // we caught em all
404- // const FIXME_TEMPORARY_ATTR_ALLOWLIST: &[Symbol] = &[sym::cfg];
405- // assert!(
406- // self.tools.contains(&parts[0]) || true,
407- // // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
408- // "attribute {path} wasn't parsed and isn't a know tool attribute",
409- // );
410-
411- attributes. push ( Attribute :: Unparsed ( Box :: new ( AttrItem {
401+ let attr = AttrItem {
412402 path : attr_path. clone ( ) ,
413403 args : self
414404 . lower_attr_args ( n. item . args . unparsed_ref ( ) . unwrap ( ) , lower_span) ,
415405 id : HashIgnoredAttrId { attr_id : attr. id } ,
416406 style : attr. style ,
417407 span : attr_span,
418- } ) ) ) ;
408+ } ;
409+
410+ if !matches ! ( self . stage. should_emit( ) , ShouldEmit :: Nothing )
411+ && target == Target :: Crate
412+ {
413+ self . check_invalid_crate_level_attr_item ( & attr, n. item . span ( ) ) ;
414+ }
415+
416+ let attr = Attribute :: Unparsed ( Box :: new ( attr) ) ;
417+
418+ if self . tools . contains ( & parts[ 0 ] )
419+ // FIXME: this can be removed once #152369 has been merged.
420+ // https://github.com/rust-lang/rust/pull/152369
421+ || [ sym:: allow, sym:: deny, sym:: expect, sym:: forbid, sym:: warn]
422+ . contains ( & parts[ 0 ] )
423+ {
424+ attributes. push ( attr) ;
425+ } else {
426+ dropped_attributes. push ( attr) ;
427+ }
419428 }
420429 }
421430 }
@@ -431,6 +440,12 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
431440 }
432441 }
433442
443+ if !matches ! ( self . stage. should_emit( ) , ShouldEmit :: Nothing )
444+ && target == Target :: WherePredicate
445+ {
446+ self . check_invalid_where_predicate_attrs ( attributes. iter ( ) . chain ( & dropped_attributes) ) ;
447+ }
448+
434449 attributes
435450 }
436451
0 commit comments