@@ -46,6 +46,7 @@ macro_rules! expansions {
4646 $( . $visit: ident) * $( lift . $visit_elt: ident) * ; ) * ) => {
4747 #[ derive( Copy , Clone , PartialEq , Eq ) ]
4848 pub enum ExpansionKind { OptExpr , $( $kind, ) * }
49+ #[ derive( Clone ) ]
4950 pub enum Expansion { OptExpr ( Option <P <ast:: Expr >>) , $( $kind( $ty) , ) * }
5051
5152 impl ExpansionKind {
@@ -210,12 +211,36 @@ impl Invocation {
210211
211212pub struct MacroExpander < ' a , ' b : ' a > {
212213 pub cx : & ' a mut ExtCtxt < ' b > ,
214+ partial_expansions : HashMap < Mark , PartialExpansion > ,
215+ full_expansions : HashMap < Mark , FullExpansion > ,
213216 monotonic : bool , // c.f. `cx.monotonic_expander()`
214217}
215218
219+
220+ // jseyfried (10/04/2017):
221+ // Partial expansion are macro expansions that have unexpanded macro invocations in them.
222+ // That is, the macro itself has resolved and been expanded, but it created more macro invocations
223+ // that have yet to be expanded. This is in contrast to "fully expanded" AST,
224+ // which has no macro invocations left.
225+ struct PartialExpansion {
226+ expansion : Expansion ,
227+ derives : Vec < ( Mark , Path ) > ,
228+ expansion_kind : ExpansionKind ,
229+ expansion_data : ExpansionData ,
230+ unexpanded_children : usize ,
231+ }
232+
233+ pub struct FullExpansion {
234+ pub expansion : Expansion ,
235+ pub derives : Vec < Mark > ,
236+ }
237+
216238impl < ' a , ' b > MacroExpander < ' a , ' b > {
217239 pub fn new ( cx : & ' a mut ExtCtxt < ' b > , monotonic : bool ) -> Self {
218- MacroExpander { cx : cx, monotonic : monotonic }
240+ MacroExpander {
241+ cx : cx, monotonic : monotonic,
242+ partial_expansions : HashMap :: new ( ) , full_expansions : HashMap :: new ( ) ,
243+ }
219244 }
220245
221246 pub fn expand_crate ( & mut self , mut krate : ast:: Crate ) -> ast:: Crate {
@@ -266,12 +291,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
266291 let orig_expansion_data = self . cx . current_expansion . clone ( ) ;
267292 self . cx . current_expansion . depth = 0 ;
268293
269- let ( expansion, mut invocations) = self . collect_invocations ( expansion, & [ ] ) ;
294+ let mark = self . cx . current_expansion . mark ;
295+ let mut invocations =
296+ self . collect_invocations ( mark, expansion, Vec :: new ( ) , ExpansionKind :: Items ) ;
270297 self . resolve_imports ( ) ;
271298 invocations. reverse ( ) ;
272299
273- let mut expansions = Vec :: new ( ) ;
274- let mut derives = HashMap :: new ( ) ;
275300 let mut undetermined_invocations = Vec :: new ( ) ;
276301 let ( mut progress, mut force) = ( false , !self . monotonic ) ;
277302 loop {
@@ -285,8 +310,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
285310 continue
286311 } ;
287312
288- let scope =
289- if self . monotonic { invoc . expansion_data . mark } else { orig_expansion_data. mark } ;
313+ let mark = invoc . expansion_data . mark ;
314+ let scope = if self . monotonic { mark } else { orig_expansion_data. mark } ;
290315 let ext = match self . cx . resolver . resolve_invoc ( & mut invoc, scope, force) {
291316 Ok ( ext) => Some ( ext) ,
292317 Err ( Determinacy :: Determined ) => None ,
@@ -297,16 +322,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
297322 } ;
298323
299324 progress = true ;
300- let ExpansionData { depth, mark, .. } = invoc. expansion_data ;
301325 self . cx . current_expansion = invoc. expansion_data . clone ( ) ;
302326
303327 self . cx . current_expansion . mark = scope;
304- // FIXME(jseyfried): Refactor out the following logic
305- let ( expansion, new_invocations) = if let Some ( ext) = ext {
328+ let new_invocations = if let Some ( ext) = ext {
306329 if let Some ( ext) = ext {
330+ let expansion_kind = invoc. expansion_kind ;
307331 let dummy = invoc. expansion_kind . dummy ( invoc. span ( ) ) . unwrap ( ) ;
308332 let expansion = self . expand_invoc ( invoc, & * ext) . unwrap_or ( dummy) ;
309- self . collect_invocations ( expansion, & [ ] )
333+ self . collect_invocations ( mark , expansion, Vec :: new ( ) , expansion_kind )
310334 } else if let InvocationKind :: Attr { attr : None , traits, item } = invoc. kind {
311335 if !item. derive_allowed ( ) {
312336 let attr = attr:: find_by_name ( item. attrs ( ) , "derive" )
@@ -326,60 +350,33 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
326350
327351 let item = self . fully_configure ( item)
328352 . map_attrs ( |mut attrs| { attrs. retain ( |a| a. path != "derive" ) ; attrs } ) ;
329- let item_with_markers =
330- add_derived_markers ( & mut self . cx , item. span ( ) , & traits, item. clone ( ) ) ;
331- let derives = derives. entry ( invoc. expansion_data . mark ) . or_insert_with ( Vec :: new) ;
332-
333- for path in & traits {
334- let mark = Mark :: fresh ( self . cx . current_expansion . mark ) ;
335- derives. push ( mark) ;
336- let item = match self . cx . resolver . resolve_macro (
337- Mark :: root ( ) , path, MacroKind :: Derive , false ) {
338- Ok ( ext) => match * ext {
339- BuiltinDerive ( ..) => item_with_markers. clone ( ) ,
340- _ => item. clone ( ) ,
341- } ,
342- _ => item. clone ( ) ,
343- } ;
344- invocations. push ( Invocation {
345- kind : InvocationKind :: Derive { path : path. clone ( ) , item : item } ,
346- expansion_kind : invoc. expansion_kind ,
347- expansion_data : ExpansionData {
348- mark,
349- ..invoc. expansion_data . clone ( )
350- } ,
351- } ) ;
352- }
353+ let item = add_derived_markers ( & mut self . cx , item. span ( ) , & traits, item) ;
353354 let expansion = invoc. expansion_kind
354- . expect_from_annotatables ( :: std:: iter:: once ( item_with_markers ) ) ;
355- self . collect_invocations ( expansion, derives )
355+ . expect_from_annotatables ( :: std:: iter:: once ( item ) ) ;
356+ self . collect_invocations ( mark , expansion, traits , invoc . expansion_kind )
356357 } else {
357358 unreachable ! ( )
358359 }
359360 } else {
360- self . collect_invocations ( invoc. expansion_kind . dummy ( invoc. span ( ) ) . unwrap ( ) , & [ ] )
361+ let dummy = invoc. expansion_kind . dummy ( invoc. span ( ) ) . unwrap ( ) ;
362+ self . collect_invocations ( mark, dummy, Vec :: new ( ) , invoc. expansion_kind )
361363 } ;
362364
363- if expansions. len ( ) < depth {
364- expansions. push ( Vec :: new ( ) ) ;
365- }
366- expansions[ depth - 1 ] . push ( ( mark, expansion) ) ;
367365 if !self . cx . ecfg . single_step {
368366 invocations. extend ( new_invocations. into_iter ( ) . rev ( ) ) ;
369367 }
370368 }
371369
372370 self . cx . current_expansion = orig_expansion_data;
371+ self . placeholder_expander ( ) . remove ( NodeId :: placeholder_from_mark ( mark) )
372+ }
373373
374- let mut placeholder_expander = PlaceholderExpander :: new ( self . cx , self . monotonic ) ;
375- while let Some ( expansions) = expansions. pop ( ) {
376- for ( mark, expansion) in expansions. into_iter ( ) . rev ( ) {
377- let derives = derives. remove ( & mark) . unwrap_or_else ( Vec :: new) ;
378- placeholder_expander. add ( NodeId :: placeholder_from_mark ( mark) , expansion, derives) ;
379- }
374+ fn placeholder_expander < ' c > ( & ' c mut self ) -> PlaceholderExpander < ' c , ' b > {
375+ PlaceholderExpander {
376+ cx : self . cx ,
377+ expansions : & mut self . full_expansions ,
378+ monotonic : self . monotonic ,
380379 }
381-
382- expansion. fold_with ( & mut placeholder_expander)
383380 }
384381
385382 fn resolve_imports ( & mut self ) {
@@ -390,30 +387,91 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
390387 }
391388 }
392389
393- fn collect_invocations ( & mut self , expansion : Expansion , derives : & [ Mark ] )
394- -> ( Expansion , Vec < Invocation > ) {
395- let result = {
390+ fn collect_invocations ( & mut self ,
391+ mut mark : Mark ,
392+ expansion : Expansion ,
393+ traits : Vec < Path > ,
394+ expansion_kind : ExpansionKind )
395+ -> Vec < Invocation > {
396+ let ( expansion, mut invocations) = {
396397 let mut collector = InvocationCollector {
397398 cfg : StripUnconfigured {
398399 should_test : self . cx . ecfg . should_test ,
399400 sess : self . cx . parse_sess ,
400401 features : self . cx . ecfg . features ,
401402 } ,
402403 cx : self . cx ,
404+ mark : mark,
403405 invocations : Vec :: new ( ) ,
404406 monotonic : self . monotonic ,
405407 } ;
406408 ( expansion. fold_with ( & mut collector) , collector. invocations )
407409 } ;
408410
411+ let mark_parent = mark. parent ( ) ;
412+ let derives: Vec < _ > =
413+ traits. into_iter ( ) . map ( |path| ( Mark :: fresh ( mark_parent) , path) ) . collect ( ) ;
414+ if derives. len ( ) > 0 {
415+ self . partial_expansions . get_mut ( & mark_parent) . unwrap ( ) . unexpanded_children +=
416+ derives. len ( ) ;
417+ }
418+
409419 if self . monotonic {
410420 let err_count = self . cx . parse_sess . span_diagnostic . err_count ( ) ;
411421 let mark = self . cx . current_expansion . mark ;
412- self . cx . resolver . visit_expansion ( mark, & result . 0 , derives) ;
422+ self . cx . resolver . visit_expansion ( mark, & expansion , & derives) ;
413423 self . cx . resolve_err_count += self . cx . parse_sess . span_diagnostic . err_count ( ) - err_count;
414424 }
415425
416- result
426+ self . partial_expansions . insert ( mark, PartialExpansion {
427+ expansion : expansion, derives : derives, expansion_kind : expansion_kind,
428+ expansion_data : self . cx . current_expansion . clone ( ) ,
429+ unexpanded_children : invocations. len ( ) ,
430+ } ) ;
431+
432+ if !invocations. is_empty ( ) {
433+ return invocations;
434+ }
435+
436+ loop {
437+ let partial_expansion = self . partial_expansions . remove ( & mark) . unwrap ( ) ;
438+ let expansion = partial_expansion. expansion . fold_with ( & mut self . placeholder_expander ( ) ) ;
439+
440+ let PartialExpansion { expansion_kind, ref expansion_data, .. } = partial_expansion;
441+ let derives = partial_expansion. derives . into_iter ( ) . map ( |( mark, path) | {
442+ let item = match expansion. clone ( ) {
443+ Expansion :: Items ( mut items) => Annotatable :: Item ( items. pop ( ) . unwrap ( ) ) ,
444+ Expansion :: TraitItems ( mut items) =>
445+ Annotatable :: TraitItem ( P ( items. pop ( ) . unwrap ( ) ) ) ,
446+ Expansion :: ImplItems ( mut items) =>
447+ Annotatable :: ImplItem ( P ( items. pop ( ) . unwrap ( ) ) ) ,
448+ _ => panic ! ( "expected item" ) ,
449+ } ;
450+ invocations. push ( Invocation {
451+ kind : InvocationKind :: Derive { path : path, item : item } ,
452+ expansion_kind : expansion_kind,
453+ expansion_data : ExpansionData { mark : mark, ..expansion_data. clone ( ) } ,
454+ } ) ;
455+ mark
456+ } ) . collect ( ) ;
457+
458+ self . full_expansions
459+ . insert ( mark, FullExpansion { expansion : expansion, derives : derives } ) ;
460+
461+ if mark == Mark :: root ( ) {
462+ break
463+ }
464+ mark = mark. parent ( ) ;
465+ if let Some ( partial_expansion) = self . partial_expansions . get_mut ( & mark) {
466+ partial_expansion. unexpanded_children -= 1 ;
467+ if partial_expansion. unexpanded_children == 0 {
468+ continue
469+ }
470+ }
471+ break
472+ }
473+
474+ invocations
417475 }
418476
419477 fn fully_configure ( & mut self , item : Annotatable ) -> Annotatable {
@@ -793,14 +851,15 @@ impl<'a> Parser<'a> {
793851
794852struct InvocationCollector < ' a , ' b : ' a > {
795853 cx : & ' a mut ExtCtxt < ' b > ,
854+ mark : Mark ,
796855 cfg : StripUnconfigured < ' a > ,
797856 invocations : Vec < Invocation > ,
798857 monotonic : bool ,
799858}
800859
801860impl < ' a , ' b > InvocationCollector < ' a , ' b > {
802861 fn collect ( & mut self , expansion_kind : ExpansionKind , kind : InvocationKind ) -> Expansion {
803- let mark = Mark :: fresh ( self . cx . current_expansion . mark ) ;
862+ let mark = Mark :: fresh ( self . mark ) ;
804863 self . invocations . push ( Invocation {
805864 kind,
806865 expansion_kind,
@@ -1180,7 +1239,6 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
11801239
11811240 fn new_id ( & mut self , id : ast:: NodeId ) -> ast:: NodeId {
11821241 if self . monotonic {
1183- assert_eq ! ( id, ast:: DUMMY_NODE_ID ) ;
11841242 self . cx . resolver . next_node_id ( )
11851243 } else {
11861244 id
0 commit comments