@@ -44,6 +44,7 @@ macro_rules! expansions {
44
44
$( . $visit: ident) * $( lift . $visit_elt: ident) * ; ) * ) => {
45
45
#[ derive( Copy , Clone , PartialEq , Eq ) ]
46
46
pub enum ExpansionKind { OptExpr , $( $kind, ) * }
47
+ #[ derive( Clone ) ]
47
48
pub enum Expansion { OptExpr ( Option <P <ast:: Expr >>) , $( $kind( $ty) , ) * }
48
49
49
50
impl ExpansionKind {
@@ -188,12 +189,30 @@ impl Invocation {
188
189
189
190
pub struct MacroExpander < ' a , ' b : ' a > {
190
191
pub cx : & ' a mut ExtCtxt < ' b > ,
192
+ partial_expansions : HashMap < Mark , PartialExpansion > ,
193
+ full_expansions : HashMap < Mark , FullExpansion > ,
191
194
monotonic : bool , // c.f. `cx.monotonic_expander()`
192
195
}
193
196
197
+ struct PartialExpansion {
198
+ expansion : Expansion ,
199
+ derives : Vec < ( Mark , Path ) > ,
200
+ expansion_kind : ExpansionKind ,
201
+ expansion_data : ExpansionData ,
202
+ unexpanded_children : usize ,
203
+ }
204
+
205
+ pub struct FullExpansion {
206
+ pub expansion : Expansion ,
207
+ pub derives : Vec < Mark > ,
208
+ }
209
+
194
210
impl < ' a , ' b > MacroExpander < ' a , ' b > {
195
211
pub fn new ( cx : & ' a mut ExtCtxt < ' b > , monotonic : bool ) -> Self {
196
- MacroExpander { cx : cx, monotonic : monotonic }
212
+ MacroExpander {
213
+ cx : cx, monotonic : monotonic,
214
+ partial_expansions : HashMap :: new ( ) , full_expansions : HashMap :: new ( ) ,
215
+ }
197
216
}
198
217
199
218
pub fn expand_crate ( & mut self , mut krate : ast:: Crate ) -> ast:: Crate {
@@ -230,12 +249,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
230
249
let orig_expansion_data = self . cx . current_expansion . clone ( ) ;
231
250
self . cx . current_expansion . depth = 0 ;
232
251
233
- let ( expansion, mut invocations) = self . collect_invocations ( expansion, & [ ] ) ;
252
+ let mark = self . cx . current_expansion . mark ;
253
+ let mut invocations =
254
+ self . collect_invocations ( mark, expansion, Vec :: new ( ) , ExpansionKind :: Items ) ;
234
255
self . resolve_imports ( ) ;
235
256
invocations. reverse ( ) ;
236
257
237
- let mut expansions = Vec :: new ( ) ;
238
- let mut derives = HashMap :: new ( ) ;
239
258
let mut undetermined_invocations = Vec :: new ( ) ;
240
259
let ( mut progress, mut force) = ( false , !self . monotonic ) ;
241
260
loop {
@@ -249,8 +268,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
249
268
continue
250
269
} ;
251
270
252
- let scope =
253
- if self . monotonic { invoc . expansion_data . mark } else { orig_expansion_data. mark } ;
271
+ let mark = invoc . expansion_data . mark ;
272
+ let scope = if self . monotonic { mark } else { orig_expansion_data. mark } ;
254
273
let ext = match self . cx . resolver . resolve_invoc ( & mut invoc, scope, force) {
255
274
Ok ( ext) => Some ( ext) ,
256
275
Err ( Determinacy :: Determined ) => None ,
@@ -261,72 +280,44 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
261
280
} ;
262
281
263
282
progress = true ;
264
- let ExpansionData { depth, mark, .. } = invoc. expansion_data ;
265
283
self . cx . current_expansion = invoc. expansion_data . clone ( ) ;
266
284
267
285
self . cx . current_expansion . mark = scope;
268
- // FIXME(jseyfried): Refactor out the following logic
269
- let ( expansion, new_invocations) = if let Some ( ext) = ext {
286
+ let new_invocations = if let Some ( ext) = ext {
270
287
if let Some ( ext) = ext {
288
+ let expansion_kind = invoc. expansion_kind ;
271
289
let expansion = self . expand_invoc ( invoc, ext) ;
272
- self . collect_invocations ( expansion, & [ ] )
290
+ self . collect_invocations ( mark , expansion, Vec :: new ( ) , expansion_kind )
273
291
} else if let InvocationKind :: Attr { attr : None , traits, item } = invoc. kind {
274
292
let item = item
275
293
. map_attrs ( |mut attrs| { attrs. retain ( |a| a. path != "derive" ) ; attrs } ) ;
276
- let item_with_markers =
277
- add_derived_markers ( & mut self . cx , item. span ( ) , & traits, item. clone ( ) ) ;
278
- let derives = derives. entry ( invoc. expansion_data . mark ) . or_insert_with ( Vec :: new) ;
279
-
280
- for path in & traits {
281
- let mark = Mark :: fresh ( ) ;
282
- derives. push ( mark) ;
283
- let item = match self . cx . resolver . resolve_macro (
284
- Mark :: root ( ) , path, MacroKind :: Derive , false ) {
285
- Ok ( ext) => match * ext {
286
- SyntaxExtension :: BuiltinDerive ( ..) => item_with_markers. clone ( ) ,
287
- _ => item. clone ( ) ,
288
- } ,
289
- _ => item. clone ( ) ,
290
- } ;
291
- invocations. push ( Invocation {
292
- kind : InvocationKind :: Derive { path : path. clone ( ) , item : item } ,
293
- expansion_kind : invoc. expansion_kind ,
294
- expansion_data : ExpansionData {
295
- mark : mark,
296
- ..invoc. expansion_data . clone ( )
297
- } ,
298
- } ) ;
299
- }
294
+ let item = add_derived_markers ( & mut self . cx , item. span ( ) , & traits, item) ;
300
295
let expansion = invoc. expansion_kind
301
- . expect_from_annotatables ( :: std:: iter:: once ( item_with_markers ) ) ;
302
- self . collect_invocations ( expansion, derives )
296
+ . expect_from_annotatables ( :: std:: iter:: once ( item ) ) ;
297
+ self . collect_invocations ( mark , expansion, traits , invoc . expansion_kind )
303
298
} else {
304
299
unreachable ! ( )
305
300
}
306
301
} else {
307
- self . collect_invocations ( invoc. expansion_kind . dummy ( invoc. span ( ) ) , & [ ] )
302
+ let dummy = invoc. expansion_kind . dummy ( invoc. span ( ) ) ;
303
+ self . collect_invocations ( mark, dummy, Vec :: new ( ) , invoc. expansion_kind )
308
304
} ;
309
305
310
- if expansions. len ( ) < depth {
311
- expansions. push ( Vec :: new ( ) ) ;
312
- }
313
- expansions[ depth - 1 ] . push ( ( mark, expansion) ) ;
314
306
if !self . cx . ecfg . single_step {
315
307
invocations. extend ( new_invocations. into_iter ( ) . rev ( ) ) ;
316
308
}
317
309
}
318
310
319
311
self . cx . current_expansion = orig_expansion_data;
312
+ self . placeholder_expander ( ) . remove ( NodeId :: placeholder_from_mark ( mark) )
313
+ }
320
314
321
- let mut placeholder_expander = PlaceholderExpander :: new ( self . cx , self . monotonic ) ;
322
- while let Some ( expansions) = expansions. pop ( ) {
323
- for ( mark, expansion) in expansions. into_iter ( ) . rev ( ) {
324
- let derives = derives. remove ( & mark) . unwrap_or_else ( Vec :: new) ;
325
- placeholder_expander. add ( NodeId :: placeholder_from_mark ( mark) , expansion, derives) ;
326
- }
315
+ fn placeholder_expander < ' c > ( & ' c mut self ) -> PlaceholderExpander < ' c , ' b > {
316
+ PlaceholderExpander {
317
+ cx : self . cx ,
318
+ expansions : & mut self . full_expansions ,
319
+ monotonic : self . monotonic ,
327
320
}
328
-
329
- expansion. fold_with ( & mut placeholder_expander)
330
321
}
331
322
332
323
fn resolve_imports ( & mut self ) {
@@ -337,30 +328,91 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
337
328
}
338
329
}
339
330
340
- fn collect_invocations ( & mut self , expansion : Expansion , derives : & [ Mark ] )
341
- -> ( Expansion , Vec < Invocation > ) {
342
- let result = {
331
+ fn collect_invocations ( & mut self ,
332
+ mut mark : Mark ,
333
+ expansion : Expansion ,
334
+ traits : Vec < Path > ,
335
+ expansion_kind : ExpansionKind )
336
+ -> Vec < Invocation > {
337
+ let ( expansion, mut invocations) = {
343
338
let mut collector = InvocationCollector {
344
339
cfg : StripUnconfigured {
345
340
should_test : self . cx . ecfg . should_test ,
346
341
sess : self . cx . parse_sess ,
347
342
features : self . cx . ecfg . features ,
348
343
} ,
349
344
cx : self . cx ,
345
+ mark : mark,
350
346
invocations : Vec :: new ( ) ,
351
347
monotonic : self . monotonic ,
352
348
} ;
353
349
( expansion. fold_with ( & mut collector) , collector. invocations )
354
350
} ;
355
351
352
+ let mark_parent = mark. parent ( ) ;
353
+ let derives: Vec < _ > =
354
+ traits. into_iter ( ) . map ( |path| ( Mark :: fresh ( mark_parent) , path) ) . collect ( ) ;
355
+ if derives. len ( ) > 0 {
356
+ self . partial_expansions . get_mut ( & mark_parent) . unwrap ( ) . unexpanded_children +=
357
+ derives. len ( ) ;
358
+ }
359
+
356
360
if self . monotonic {
357
361
let err_count = self . cx . parse_sess . span_diagnostic . err_count ( ) ;
358
362
let mark = self . cx . current_expansion . mark ;
359
- self . cx . resolver . visit_expansion ( mark, & result . 0 , derives) ;
363
+ self . cx . resolver . visit_expansion ( mark, & expansion , & derives) ;
360
364
self . cx . resolve_err_count += self . cx . parse_sess . span_diagnostic . err_count ( ) - err_count;
361
365
}
362
366
363
- result
367
+ self . partial_expansions . insert ( mark, PartialExpansion {
368
+ expansion : expansion, derives : derives, expansion_kind : expansion_kind,
369
+ expansion_data : self . cx . current_expansion . clone ( ) ,
370
+ unexpanded_children : invocations. len ( ) ,
371
+ } ) ;
372
+
373
+ if !invocations. is_empty ( ) {
374
+ return invocations;
375
+ }
376
+
377
+ loop {
378
+ let partial_expansion = self . partial_expansions . remove ( & mark) . unwrap ( ) ;
379
+ let expansion = partial_expansion. expansion . fold_with ( & mut self . placeholder_expander ( ) ) ;
380
+
381
+ let PartialExpansion { expansion_kind, ref expansion_data, .. } = partial_expansion;
382
+ let derives = partial_expansion. derives . into_iter ( ) . map ( |( mark, path) | {
383
+ let item = match expansion. clone ( ) {
384
+ Expansion :: Items ( mut items) => Annotatable :: Item ( items. pop ( ) . unwrap ( ) ) ,
385
+ Expansion :: TraitItems ( mut items) =>
386
+ Annotatable :: TraitItem ( P ( items. pop ( ) . unwrap ( ) ) ) ,
387
+ Expansion :: ImplItems ( mut items) =>
388
+ Annotatable :: ImplItem ( P ( items. pop ( ) . unwrap ( ) ) ) ,
389
+ _ => panic ! ( "expected item" ) ,
390
+ } ;
391
+ invocations. push ( Invocation {
392
+ kind : InvocationKind :: Derive { path : path, item : item } ,
393
+ expansion_kind : expansion_kind,
394
+ expansion_data : ExpansionData { mark : mark, ..expansion_data. clone ( ) } ,
395
+ } ) ;
396
+ mark
397
+ } ) . collect ( ) ;
398
+
399
+ self . full_expansions
400
+ . insert ( mark, FullExpansion { expansion : expansion, derives : derives } ) ;
401
+
402
+ if mark == Mark :: root ( ) {
403
+ break
404
+ }
405
+ mark = mark. parent ( ) ;
406
+ if let Some ( partial_expansion) = self . partial_expansions . get_mut ( & mark) {
407
+ partial_expansion. unexpanded_children -= 1 ;
408
+ if partial_expansion. unexpanded_children == 0 {
409
+ continue
410
+ }
411
+ }
412
+ break
413
+ }
414
+
415
+ invocations
364
416
}
365
417
366
418
fn expand_invoc ( & mut self , invoc : Invocation , ext : Rc < SyntaxExtension > ) -> Expansion {
@@ -661,6 +713,7 @@ impl<'a> Parser<'a> {
661
713
662
714
struct InvocationCollector < ' a , ' b : ' a > {
663
715
cx : & ' a mut ExtCtxt < ' b > ,
716
+ mark : Mark ,
664
717
cfg : StripUnconfigured < ' a > ,
665
718
invocations : Vec < Invocation > ,
666
719
monotonic : bool ,
@@ -677,7 +730,7 @@ macro_rules! fully_configure {
677
730
678
731
impl < ' a , ' b > InvocationCollector < ' a , ' b > {
679
732
fn collect ( & mut self , expansion_kind : ExpansionKind , kind : InvocationKind ) -> Expansion {
680
- let mark = Mark :: fresh ( ) ;
733
+ let mark = Mark :: fresh ( self . mark ) ;
681
734
self . invocations . push ( Invocation {
682
735
kind : kind,
683
736
expansion_kind : expansion_kind,
@@ -992,7 +1045,6 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
992
1045
993
1046
fn new_id ( & mut self , id : ast:: NodeId ) -> ast:: NodeId {
994
1047
if self . monotonic {
995
- assert_eq ! ( id, ast:: DUMMY_NODE_ID ) ;
996
1048
self . cx . resolver . next_node_id ( )
997
1049
} else {
998
1050
id
0 commit comments