@@ -86,7 +86,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
86
86
// expr_mac should really be expr_ext or something; it's the
87
87
// entry-point for all syntax extensions.
88
88
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)
90
90
}
91
91
92
92
ast:: ExprKind :: InPlace ( placer, value_expr) => {
@@ -196,21 +196,17 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
196
196
} ) ;
197
197
}
198
198
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 ,
201
201
fld : & mut MacroExpander ) -> T
202
202
where T : MacroGenerable ,
203
203
{
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.
210
206
let Mac_ { path, tts, .. } = mac. node ;
211
207
let mark = fresh_mark ( ) ;
212
208
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 ,
214
210
attrs : Vec < ast:: Attribute > , call_site : Span , fld : & ' a mut MacroExpander )
215
211
-> Option < Box < MacResult + ' a > > {
216
212
check_attributes ( & attrs, fld) ;
@@ -231,8 +227,16 @@ fn expand_mac_invoc<T>(mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span,
231
227
return None ;
232
228
} ;
233
229
230
+ let ident = ident. unwrap_or ( Ident :: with_empty_ctxt ( keywords:: Invalid . name ( ) ) ) ;
234
231
match * extension {
235
232
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
+
236
240
fld. cx . bt_push ( ExpnInfo {
237
241
call_site : call_site,
238
242
callee : NameAndSpan {
@@ -251,15 +255,72 @@ fn expand_mac_invoc<T>(mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span,
251
255
let marked_tts = mark_tts ( & tts[ ..] , mark) ;
252
256
Some ( expandfun. expand ( fld. cx , mac_span, & marked_tts) )
253
257
}
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 ( ..) => {
255
316
fld. cx . span_err ( path. span ,
256
- & format ! ( "'{}' is not a tt-style macro " , extname) ) ;
317
+ & format ! ( "`{}` can only be used in attributes " , extname) ) ;
257
318
None
258
319
}
259
320
}
260
321
}
261
322
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) {
263
324
Some ( result) => result,
264
325
None => return T :: dummy ( span) ,
265
326
} ) ;
@@ -375,141 +436,6 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool
375
436
false
376
437
}
377
438
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
-
513
439
/// Expand a stmt
514
440
fn expand_stmt ( stmt : Stmt , fld : & mut MacroExpander ) -> SmallVector < Stmt > {
515
441
// perform all pending renames
@@ -525,7 +451,7 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
525
451
} ;
526
452
527
453
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) ;
529
455
530
456
// If this is a macro invocation with a semicolon, then apply that
531
457
// 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> {
742
668
}
743
669
p. and_then ( |ast:: Pat { node, span, ..} | {
744
670
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) ,
746
672
_ => unreachable ! ( )
747
673
}
748
674
} )
@@ -813,7 +739,13 @@ fn expand_annotatable(a: Annotatable,
813
739
let mut new_items: SmallVector < Annotatable > = match a {
814
740
Annotatable :: Item ( it) => match it. node {
815
741
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 ( )
817
749
}
818
750
ast:: ItemKind :: Mod ( _) | ast:: ItemKind :: ForeignMod ( _) => {
819
751
let valid_ident =
@@ -997,7 +929,7 @@ fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
997
929
span : fld. new_span ( ii. span )
998
930
} ) ,
999
931
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)
1001
933
}
1002
934
_ => fold:: noop_fold_impl_item ( ii, fld)
1003
935
}
@@ -1041,7 +973,7 @@ pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander) -> P<ast::Ty> {
1041
973
let t = match t. node . clone ( ) {
1042
974
ast:: TyKind :: Mac ( mac) => {
1043
975
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)
1045
977
} else {
1046
978
feature_gate:: emit_feature_err (
1047
979
& fld. cx . parse_sess . span_diagnostic ,
@@ -1310,12 +1242,6 @@ fn mark_tts(tts: &[TokenTree], m: Mrk) -> Vec<TokenTree> {
1310
1242
noop_fold_tts ( tts, & mut Marker { mark : m} )
1311
1243
}
1312
1244
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
-
1319
1245
/// Check that there are no macro invocations left in the AST:
1320
1246
pub fn check_for_macros ( sess : & parse:: ParseSess , krate : & ast:: Crate ) {
1321
1247
visit:: walk_crate ( & mut MacroExterminator { sess : sess} , krate) ;
0 commit comments