@@ -86,7 +86,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
8686 // expr_mac should really be expr_ext or something; it's the
8787 // entry-point for all syntax extensions.
8888 ast:: ExprKind :: Mac ( mac) => {
89- expand_mac_invoc ( mac, attrs. into_attr_vec ( ) , span, fld)
89+ expand_mac_invoc ( mac, None , attrs. into_attr_vec ( ) , span, fld)
9090 }
9191
9292 ast:: ExprKind :: InPlace ( placer, value_expr) => {
@@ -196,21 +196,17 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
196196 } ) ;
197197}
198198
199- /// Expand a (not-ident-style) macro invocation. Returns the result of expansion.
200- fn expand_mac_invoc < T > ( mac : ast:: Mac , attrs : Vec < ast:: Attribute > , span : Span ,
199+ /// Expand a macro invocation. Returns the result of expansion.
200+ fn expand_mac_invoc < T > ( mac : ast:: Mac , ident : Option < Ident > , attrs : Vec < ast:: Attribute > , span : Span ,
201201 fld : & mut MacroExpander ) -> T
202202 where T : MacroGenerable ,
203203{
204- // it would almost certainly be cleaner to pass the whole
205- // macro invocation in, rather than pulling it apart and
206- // marking the tts and the ctxt separately. This also goes
207- // for the other three macro invocation chunks of code
208- // in this file.
209-
204+ // It would almost certainly be cleaner to pass the whole macro invocation in,
205+ // rather than pulling it apart and marking the tts and the ctxt separately.
210206 let Mac_ { path, tts, .. } = mac. node ;
211207 let mark = fresh_mark ( ) ;
212208
213- fn mac_result < ' a > ( path : & ast:: Path , tts : Vec < TokenTree > , mark : Mrk ,
209+ fn mac_result < ' a > ( path : & ast:: Path , ident : Option < Ident > , tts : Vec < TokenTree > , mark : Mrk ,
214210 attrs : Vec < ast:: Attribute > , call_site : Span , fld : & ' a mut MacroExpander )
215211 -> Option < Box < MacResult + ' a > > {
216212 check_attributes ( & attrs, fld) ;
@@ -231,8 +227,16 @@ fn expand_mac_invoc<T>(mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span,
231227 return None ;
232228 } ;
233229
230+ let ident = ident. unwrap_or ( Ident :: with_empty_ctxt ( keywords:: Invalid . name ( ) ) ) ;
234231 match * extension {
235232 NormalTT ( ref expandfun, exp_span, allow_internal_unstable) => {
233+ if ident. name != keywords:: Invalid . name ( ) {
234+ let msg =
235+ format ! ( "macro {}! expects no ident argument, given '{}'" , extname, ident) ;
236+ fld. cx . span_err ( path. span , & msg) ;
237+ return None ;
238+ }
239+
236240 fld. cx . bt_push ( ExpnInfo {
237241 call_site : call_site,
238242 callee : NameAndSpan {
@@ -251,15 +255,72 @@ fn expand_mac_invoc<T>(mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span,
251255 let marked_tts = mark_tts ( & tts[ ..] , mark) ;
252256 Some ( expandfun. expand ( fld. cx , mac_span, & marked_tts) )
253257 }
254- _ => {
258+
259+ IdentTT ( ref expander, tt_span, allow_internal_unstable) => {
260+ if ident. name == keywords:: Invalid . name ( ) {
261+ fld. cx . span_err ( path. span ,
262+ & format ! ( "macro {}! expects an ident argument" , extname) ) ;
263+ return None ;
264+ } ;
265+
266+ fld. cx . bt_push ( ExpnInfo {
267+ call_site : call_site,
268+ callee : NameAndSpan {
269+ format : MacroBang ( extname) ,
270+ span : tt_span,
271+ allow_internal_unstable : allow_internal_unstable,
272+ }
273+ } ) ;
274+
275+ let marked_tts = mark_tts ( & tts, mark) ;
276+ Some ( expander. expand ( fld. cx , call_site, ident, marked_tts) )
277+ }
278+
279+ MacroRulesTT => {
280+ if ident. name == keywords:: Invalid . name ( ) {
281+ fld. cx . span_err ( path. span ,
282+ & format ! ( "macro {}! expects an ident argument" , extname) ) ;
283+ return None ;
284+ } ;
285+
286+ fld. cx . bt_push ( ExpnInfo {
287+ call_site : call_site,
288+ callee : NameAndSpan {
289+ format : MacroBang ( extname) ,
290+ span : None ,
291+ // `macro_rules!` doesn't directly allow unstable
292+ // (this is orthogonal to whether the macro it creates allows it)
293+ allow_internal_unstable : false ,
294+ }
295+ } ) ;
296+
297+ // DON'T mark before expansion.
298+ fld. cx . insert_macro ( ast:: MacroDef {
299+ ident : ident,
300+ id : ast:: DUMMY_NODE_ID ,
301+ span : call_site,
302+ imported_from : None ,
303+ use_locally : true ,
304+ body : tts,
305+ export : attr:: contains_name ( & attrs, "macro_export" ) ,
306+ allow_internal_unstable : attr:: contains_name ( & attrs, "allow_internal_unstable" ) ,
307+ attrs : attrs,
308+ } ) ;
309+
310+ // macro_rules! has a side effect but expands to nothing.
311+ fld. cx . bt_pop ( ) ;
312+ None
313+ }
314+
315+ MultiDecorator ( ..) | MultiModifier ( ..) => {
255316 fld. cx . span_err ( path. span ,
256- & format ! ( "'{}' is not a tt-style macro " , extname) ) ;
317+ & format ! ( "`{}` can only be used in attributes " , extname) ) ;
257318 None
258319 }
259320 }
260321 }
261322
262- let opt_expanded = T :: make_with ( match mac_result ( & path, tts, mark, attrs, span, fld) {
323+ let opt_expanded = T :: make_with ( match mac_result ( & path, ident , tts, mark, attrs, span, fld) {
263324 Some ( result) => result,
264325 None => return T :: dummy ( span) ,
265326 } ) ;
@@ -375,141 +436,6 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool
375436 false
376437}
377438
378- // Support for item-position macro invocations, exactly the same
379- // logic as for expression-position macro invocations.
380- pub fn expand_item_mac ( it : P < ast:: Item > ,
381- fld : & mut MacroExpander ) -> SmallVector < P < ast:: Item > > {
382- let ( extname, path_span, tts, span, attrs, ident) = it. and_then ( |it| match it. node {
383- ItemKind :: Mac ( codemap:: Spanned { node : Mac_ { path, tts, .. } , .. } ) =>
384- ( path. segments [ 0 ] . identifier . name , path. span , tts, it. span , it. attrs , it. ident ) ,
385- _ => fld. cx . span_bug ( it. span , "invalid item macro invocation" )
386- } ) ;
387-
388- check_attributes ( & attrs, fld) ;
389-
390- let fm = fresh_mark ( ) ;
391- let items = {
392- let expanded = match fld. cx . syntax_env . find ( extname) {
393- None => {
394- fld. cx . span_err ( path_span,
395- & format ! ( "macro undefined: '{}!'" ,
396- extname) ) ;
397- // let compilation continue
398- return SmallVector :: zero ( ) ;
399- }
400-
401- Some ( rc) => match * rc {
402- NormalTT ( ref expander, tt_span, allow_internal_unstable) => {
403- if ident. name != keywords:: Invalid . name ( ) {
404- fld. cx
405- . span_err ( path_span,
406- & format ! ( "macro {}! expects no ident argument, given '{}'" ,
407- extname,
408- ident) ) ;
409- return SmallVector :: zero ( ) ;
410- }
411- fld. cx . bt_push ( ExpnInfo {
412- call_site : span,
413- callee : NameAndSpan {
414- format : MacroBang ( extname) ,
415- span : tt_span,
416- allow_internal_unstable : allow_internal_unstable,
417- }
418- } ) ;
419- // mark before expansion:
420- let marked_before = mark_tts ( & tts[ ..] , fm) ;
421- expander. expand ( fld. cx , span, & marked_before[ ..] )
422- }
423- IdentTT ( ref expander, tt_span, allow_internal_unstable) => {
424- if ident. name == keywords:: Invalid . name ( ) {
425- fld. cx . span_err ( path_span,
426- & format ! ( "macro {}! expects an ident argument" ,
427- extname) ) ;
428- return SmallVector :: zero ( ) ;
429- }
430- fld. cx . bt_push ( ExpnInfo {
431- call_site : span,
432- callee : NameAndSpan {
433- format : MacroBang ( extname) ,
434- span : tt_span,
435- allow_internal_unstable : allow_internal_unstable,
436- }
437- } ) ;
438- // mark before expansion:
439- let marked_tts = mark_tts ( & tts[ ..] , fm) ;
440- expander. expand ( fld. cx , span, ident, marked_tts)
441- }
442- MacroRulesTT => {
443- if ident. name == keywords:: Invalid . name ( ) {
444- fld. cx . span_err ( path_span, "macro_rules! expects an ident argument" ) ;
445- return SmallVector :: zero ( ) ;
446- }
447-
448- fld. cx . bt_push ( ExpnInfo {
449- call_site : span,
450- callee : NameAndSpan {
451- format : MacroBang ( extname) ,
452- span : None ,
453- // `macro_rules!` doesn't directly allow
454- // unstable (this is orthogonal to whether
455- // the macro it creates allows it)
456- allow_internal_unstable : false ,
457- }
458- } ) ;
459- // DON'T mark before expansion.
460-
461- let allow_internal_unstable = attr:: contains_name ( & attrs,
462- "allow_internal_unstable" ) ;
463-
464- let export = attr:: contains_name ( & attrs, "macro_export" ) ;
465- let def = ast:: MacroDef {
466- ident : ident,
467- attrs : attrs,
468- id : ast:: DUMMY_NODE_ID ,
469- span : span,
470- imported_from : None ,
471- export : export,
472- use_locally : true ,
473- allow_internal_unstable : allow_internal_unstable,
474- body : tts,
475- } ;
476- fld. cx . insert_macro ( def) ;
477-
478- // macro_rules! has a side effect but expands to nothing.
479- fld. cx . bt_pop ( ) ;
480- return SmallVector :: zero ( ) ;
481- }
482- _ => {
483- fld. cx . span_err ( span,
484- & format ! ( "{}! is not legal in item position" ,
485- extname) ) ;
486- return SmallVector :: zero ( ) ;
487- }
488- }
489- } ;
490-
491- expanded. make_items ( )
492- } ;
493-
494- let items = match items {
495- Some ( items) => {
496- items. into_iter ( )
497- . map ( |i| mark_item ( i, fm) )
498- . flat_map ( |i| fld. fold_item ( i) . into_iter ( ) )
499- . collect ( )
500- }
501- None => {
502- fld. cx . span_err ( path_span,
503- & format ! ( "non-item macro in item position: {}" ,
504- extname) ) ;
505- return SmallVector :: zero ( ) ;
506- }
507- } ;
508-
509- fld. cx . bt_pop ( ) ;
510- items
511- }
512-
513439/// Expand a stmt
514440fn expand_stmt ( stmt : Stmt , fld : & mut MacroExpander ) -> SmallVector < Stmt > {
515441 // perform all pending renames
@@ -525,7 +451,7 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
525451 } ;
526452
527453 let mut fully_expanded: SmallVector < ast:: Stmt > =
528- expand_mac_invoc ( mac. unwrap ( ) , attrs. into_attr_vec ( ) , stmt. span , fld) ;
454+ expand_mac_invoc ( mac. unwrap ( ) , None , attrs. into_attr_vec ( ) , stmt. span , fld) ;
529455
530456 // If this is a macro invocation with a semicolon, then apply that
531457 // semicolon to the final statement produced by expansion.
@@ -742,7 +668,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
742668 }
743669 p. and_then ( |ast:: Pat { node, span, ..} | {
744670 match node {
745- PatKind :: Mac ( mac) => expand_mac_invoc ( mac, Vec :: new ( ) , span, fld) ,
671+ PatKind :: Mac ( mac) => expand_mac_invoc ( mac, None , Vec :: new ( ) , span, fld) ,
746672 _ => unreachable ! ( )
747673 }
748674 } )
@@ -813,7 +739,13 @@ fn expand_annotatable(a: Annotatable,
813739 let mut new_items: SmallVector < Annotatable > = match a {
814740 Annotatable :: Item ( it) => match it. node {
815741 ast:: ItemKind :: Mac ( ..) => {
816- expand_item_mac ( it, fld) . into_iter ( ) . map ( |i| Annotatable :: Item ( i) ) . collect ( )
742+ let new_items: SmallVector < P < ast:: Item > > = it. and_then ( |it| match it. node {
743+ ItemKind :: Mac ( mac) =>
744+ expand_mac_invoc ( mac, Some ( it. ident ) , it. attrs , it. span , fld) ,
745+ _ => unreachable ! ( ) ,
746+ } ) ;
747+
748+ new_items. into_iter ( ) . map ( |i| Annotatable :: Item ( i) ) . collect ( )
817749 }
818750 ast:: ItemKind :: Mod ( _) | ast:: ItemKind :: ForeignMod ( _) => {
819751 let valid_ident =
@@ -997,7 +929,7 @@ fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
997929 span : fld. new_span ( ii. span )
998930 } ) ,
999931 ast:: ImplItemKind :: Macro ( mac) => {
1000- expand_mac_invoc ( mac, ii. attrs , ii. span , fld)
932+ expand_mac_invoc ( mac, None , ii. attrs , ii. span , fld)
1001933 }
1002934 _ => fold:: noop_fold_impl_item ( ii, fld)
1003935 }
@@ -1041,7 +973,7 @@ pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander) -> P<ast::Ty> {
1041973 let t = match t. node . clone ( ) {
1042974 ast:: TyKind :: Mac ( mac) => {
1043975 if fld. cx . ecfg . features . unwrap ( ) . type_macros {
1044- expand_mac_invoc ( mac, Vec :: new ( ) , t. span , fld)
976+ expand_mac_invoc ( mac, None , Vec :: new ( ) , t. span , fld)
1045977 } else {
1046978 feature_gate:: emit_feature_err (
1047979 & fld. cx . parse_sess . span_diagnostic ,
@@ -1310,12 +1242,6 @@ fn mark_tts(tts: &[TokenTree], m: Mrk) -> Vec<TokenTree> {
13101242 noop_fold_tts ( tts, & mut Marker { mark : m} )
13111243}
13121244
1313- // apply a given mark to the given item. Used following the expansion of a macro.
1314- fn mark_item ( expr : P < ast:: Item > , m : Mrk ) -> P < ast:: Item > {
1315- Marker { mark : m} . fold_item ( expr)
1316- . expect_one ( "marking an item didn't return exactly one item" )
1317- }
1318-
13191245/// Check that there are no macro invocations left in the AST:
13201246pub fn check_for_macros ( sess : & parse:: ParseSess , krate : & ast:: Crate ) {
13211247 visit:: walk_crate ( & mut MacroExterminator { sess : sess} , krate) ;
0 commit comments