@@ -745,9 +745,17 @@ impl SyntaxExtension {
745745            } 
746746        } 
747747
748-         let  builtin_name = sess
748+         let  ( builtin_name,  helper_attrs )  = sess
749749            . find_by_name ( attrs,  sym:: rustc_builtin_macro) 
750-             . map ( |a| a. value_str ( ) . unwrap_or ( name) ) ; 
750+             . map ( |attr| { 
751+                 // Override `helper_attrs` passed above if it's a built-in macro, 
752+                 // marking `proc_macro_derive` macros as built-in is not a realistic use case. 
753+                 parse_macro_name_and_helper_attrs ( sess. diagnostic ( ) ,  attr,  "built-in" ) . map_or_else ( 
754+                     || ( Some ( name) ,  Vec :: new ( ) ) , 
755+                     |( name,  helper_attrs) | ( Some ( name) ,  helper_attrs) , 
756+                 ) 
757+             } ) 
758+             . unwrap_or_else ( || ( None ,  helper_attrs) ) ; 
751759        let  ( stability,  const_stability)  = attr:: find_stability ( & sess,  attrs,  span) ; 
752760        if  let  Some ( ( _,  sp) )  = const_stability { 
753761            sess. parse_sess 
@@ -1213,6 +1221,88 @@ pub fn get_exprs_from_tts(
12131221    Some ( es) 
12141222} 
12151223
1224+ pub  fn  parse_macro_name_and_helper_attrs ( 
1225+     diag :  & rustc_errors:: Handler , 
1226+     attr :  & Attribute , 
1227+     descr :  & str , 
1228+ )  -> Option < ( Symbol ,  Vec < Symbol > ) >  { 
1229+     // Once we've located the `#[proc_macro_derive]` attribute, verify 
1230+     // that it's of the form `#[proc_macro_derive(Foo)]` or 
1231+     // `#[proc_macro_derive(Foo, attributes(A, ..))]` 
1232+     let  list = match  attr. meta_item_list ( )  { 
1233+         Some ( list)  => list, 
1234+         None  => return  None , 
1235+     } ; 
1236+     if  list. len ( )  != 1  && list. len ( )  != 2  { 
1237+         diag. span_err ( attr. span ,  "attribute must have either one or two arguments" ) ; 
1238+         return  None ; 
1239+     } 
1240+     let  trait_attr = match  list[ 0 ] . meta_item ( )  { 
1241+         Some ( meta_item)  => meta_item, 
1242+         _ => { 
1243+             diag. span_err ( list[ 0 ] . span ( ) ,  "not a meta item" ) ; 
1244+             return  None ; 
1245+         } 
1246+     } ; 
1247+     let  trait_ident = match  trait_attr. ident ( )  { 
1248+         Some ( trait_ident)  if  trait_attr. is_word ( )  => trait_ident, 
1249+         _ => { 
1250+             diag. span_err ( trait_attr. span ,  "must only be one word" ) ; 
1251+             return  None ; 
1252+         } 
1253+     } ; 
1254+ 
1255+     if  !trait_ident. name . can_be_raw ( )  { 
1256+         diag. span_err ( 
1257+             trait_attr. span , 
1258+             & format ! ( "`{}` cannot be a name of {} macro" ,  trait_ident,  descr) , 
1259+         ) ; 
1260+     } 
1261+ 
1262+     let  attributes_attr = list. get ( 1 ) ; 
1263+     let  proc_attrs:  Vec < _ >  = if  let  Some ( attr)  = attributes_attr { 
1264+         if  !attr. has_name ( sym:: attributes)  { 
1265+             diag. span_err ( attr. span ( ) ,  "second argument must be `attributes`" ) 
1266+         } 
1267+         attr. meta_item_list ( ) 
1268+             . unwrap_or_else ( || { 
1269+                 diag. span_err ( attr. span ( ) ,  "attribute must be of form: `attributes(foo, bar)`" ) ; 
1270+                 & [ ] 
1271+             } ) 
1272+             . iter ( ) 
1273+             . filter_map ( |attr| { 
1274+                 let  attr = match  attr. meta_item ( )  { 
1275+                     Some ( meta_item)  => meta_item, 
1276+                     _ => { 
1277+                         diag. span_err ( attr. span ( ) ,  "not a meta item" ) ; 
1278+                         return  None ; 
1279+                     } 
1280+                 } ; 
1281+ 
1282+                 let  ident = match  attr. ident ( )  { 
1283+                     Some ( ident)  if  attr. is_word ( )  => ident, 
1284+                     _ => { 
1285+                         diag. span_err ( attr. span ,  "must only be one word" ) ; 
1286+                         return  None ; 
1287+                     } 
1288+                 } ; 
1289+                 if  !ident. name . can_be_raw ( )  { 
1290+                     diag. span_err ( 
1291+                         attr. span , 
1292+                         & format ! ( "`{}` cannot be a name of derive helper attribute" ,  ident) , 
1293+                     ) ; 
1294+                 } 
1295+ 
1296+                 Some ( ident. name ) 
1297+             } ) 
1298+             . collect ( ) 
1299+     }  else  { 
1300+         Vec :: new ( ) 
1301+     } ; 
1302+ 
1303+     Some ( ( trait_ident. name ,  proc_attrs) ) 
1304+ } 
1305+ 
12161306/// This nonterminal looks like some specific enums from 
12171307/// `proc-macro-hack` and `procedural-masquerade` crates. 
12181308/// We need to maintain some special pretty-printing behavior for them due to incorrect 
0 commit comments