@@ -29,7 +29,7 @@ use rustc_session::parse::feature_err;
2929use rustc_session:: { Limit , Session } ;
3030use rustc_span:: hygiene:: SyntaxContext ;
3131use rustc_span:: { ErrorGuaranteed , FileName , Ident , LocalExpnId , Span , Symbol , sym} ;
32- use smallvec:: SmallVec ;
32+ use smallvec:: { SmallVec , smallvec } ;
3333
3434use crate :: base:: * ;
3535use crate :: config:: { StripUnconfigured , attr_into_trace} ;
@@ -46,6 +46,22 @@ use crate::module::{
4646use crate :: placeholders:: { PlaceholderExpander , placeholder} ;
4747use crate :: stats:: * ;
4848
49+ /// Visitor to apply diagnostic attributes to expanded AST fragments
50+ struct DiagnosticAttrApplier {
51+ attrs : Vec < ast:: Attribute > ,
52+ }
53+
54+ impl MutVisitor for DiagnosticAttrApplier {
55+ fn flat_map_item ( & mut self , item : Box < ast:: Item > ) -> SmallVec < [ Box < ast:: Item > ; 1 ] > {
56+ let mut new_item = item;
57+ // Prepend diagnostic attributes to preserve their position
58+ let mut new_attrs = self . attrs . clone ( ) ;
59+ new_attrs. extend ( new_item. attrs ) ;
60+ new_item. attrs = new_attrs. into ( ) ;
61+ smallvec ! [ new_item]
62+ }
63+ }
64+
4965macro_rules! ast_fragments {
5066 (
5167 $( $Kind: ident( $AstTy: ty) {
@@ -818,12 +834,43 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
818834 let inner_tokens = attr_item. args . inner_tokens ( ) ;
819835 match expander. expand ( self . cx , span, inner_tokens, tokens) {
820836 Ok ( tok_result) => {
821- let fragment = self . parse_ast_fragment (
837+ // Extract diagnostic attributes from the original item before parsing
838+ let diagnostic_attrs = {
839+ match & item {
840+ Annotatable :: Item ( item) => item
841+ . attrs
842+ . iter ( )
843+ . filter ( |attr| {
844+ attr. name ( ) . map_or ( false , |name| {
845+ matches ! (
846+ name,
847+ sym:: expect
848+ | sym:: allow
849+ | sym:: warn
850+ | sym:: deny
851+ | sym:: forbid
852+ )
853+ } )
854+ } )
855+ . cloned ( )
856+ . collect :: < Vec < _ > > ( ) ,
857+ _ => Vec :: new ( ) ,
858+ }
859+ } ;
860+
861+ let mut fragment = self . parse_ast_fragment (
822862 tok_result,
823863 fragment_kind,
824864 & attr_item. path ,
825865 span,
826866 ) ;
867+
868+ // Apply diagnostic attributes to the expanded fragment
869+ if !diagnostic_attrs. is_empty ( ) {
870+ fragment. mut_visit_with ( & mut DiagnosticAttrApplier {
871+ attrs : diagnostic_attrs,
872+ } ) ;
873+ }
827874 if macro_stats {
828875 update_attr_macro_stats (
829876 self . cx ,
0 commit comments