@@ -408,7 +408,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
408408 let mut undetermined_invocations = Vec :: new ( ) ;
409409 let ( mut progress, mut force) = ( false , !self . monotonic ) ;
410410 loop {
411- let invoc = if let Some ( invoc) = invocations. pop ( ) {
411+ let ( invoc, res ) = if let Some ( invoc) = invocations. pop ( ) {
412412 invoc
413413 } else {
414414 self . resolve_imports ( ) ;
@@ -420,30 +420,51 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
420420 continue ;
421421 } ;
422422
423- let eager_expansion_root =
424- if self . monotonic { invoc. expansion_data . id } else { orig_expansion_data. id } ;
425- let res = match self . cx . resolver . resolve_macro_invocation (
426- & invoc,
427- eager_expansion_root,
428- force,
429- ) {
430- Ok ( res) => res,
431- Err ( Indeterminate ) => {
432- undetermined_invocations. push ( invoc) ;
433- continue ;
423+ let res = match res {
424+ Some ( res) => res,
425+ None => {
426+ let eager_expansion_root = if self . monotonic {
427+ invoc. expansion_data . id
428+ } else {
429+ orig_expansion_data. id
430+ } ;
431+ match self . cx . resolver . resolve_macro_invocation (
432+ & invoc,
433+ eager_expansion_root,
434+ force,
435+ ) {
436+ Ok ( res) => res,
437+ Err ( Indeterminate ) => {
438+ // Cannot resolve, will retry this invocation later.
439+ undetermined_invocations. push ( ( invoc, None ) ) ;
440+ continue ;
441+ }
442+ }
434443 }
435444 } ;
436445
437- progress = true ;
438446 let ExpansionData { depth, id : expn_id, .. } = invoc. expansion_data ;
439447 self . cx . current_expansion = invoc. expansion_data . clone ( ) ;
440448
441449 // FIXME(jseyfried): Refactor out the following logic
442450 let ( expanded_fragment, new_invocations) = match res {
443- InvocationRes :: Single ( ext) => {
444- let fragment = self . expand_invoc ( invoc, & ext. kind ) ;
445- self . collect_invocations ( fragment, & [ ] )
446- }
451+ InvocationRes :: Single ( ext) => match self . expand_invoc ( invoc, & ext. kind ) {
452+ ExpandResult :: Ready ( fragment) => self . collect_invocations ( fragment, & [ ] ) ,
453+ ExpandResult :: Retry ( invoc, explanation) => {
454+ if force {
455+ // We are stuck, stop retrying and produce a dummy fragment.
456+ let span = invoc. span ( ) ;
457+ self . cx . span_err ( span, & explanation) ;
458+ let fragment = invoc. fragment_kind . dummy ( span) ;
459+ self . collect_invocations ( fragment, & [ ] )
460+ } else {
461+ // Cannot expand, will retry this invocation later.
462+ undetermined_invocations
463+ . push ( ( invoc, Some ( InvocationRes :: Single ( ext) ) ) ) ;
464+ continue ;
465+ }
466+ }
467+ } ,
447468 InvocationRes :: DeriveContainer ( _exts) => {
448469 // FIXME: Consider using the derive resolutions (`_exts`) immediately,
449470 // instead of enqueuing the derives to be resolved again later.
@@ -463,21 +484,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
463484 for path in derives {
464485 let expn_id = ExpnId :: fresh ( None ) ;
465486 derive_placeholders. push ( NodeId :: placeholder_from_expn_id ( expn_id) ) ;
466- invocations. push ( Invocation {
467- kind : InvocationKind :: Derive { path, item : item. clone ( ) } ,
468- fragment_kind : invoc. fragment_kind ,
469- expansion_data : ExpansionData {
470- id : expn_id,
471- ..invoc. expansion_data . clone ( )
487+ invocations. push ( (
488+ Invocation {
489+ kind : InvocationKind :: Derive { path, item : item. clone ( ) } ,
490+ fragment_kind : invoc. fragment_kind ,
491+ expansion_data : ExpansionData {
492+ id : expn_id,
493+ ..invoc. expansion_data . clone ( )
494+ } ,
472495 } ,
473- } ) ;
496+ None ,
497+ ) ) ;
474498 }
475499 let fragment =
476500 invoc. fragment_kind . expect_from_annotatables ( :: std:: iter:: once ( item) ) ;
477501 self . collect_invocations ( fragment, & derive_placeholders)
478502 }
479503 } ;
480504
505+ progress = true ;
481506 if expanded_fragments. len ( ) < depth {
482507 expanded_fragments. push ( Vec :: new ( ) ) ;
483508 }
@@ -535,7 +560,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
535560 & mut self ,
536561 mut fragment : AstFragment ,
537562 extra_placeholders : & [ NodeId ] ,
538- ) -> ( AstFragment , Vec < Invocation > ) {
563+ ) -> ( AstFragment , Vec < ( Invocation , Option < InvocationRes > ) > ) {
539564 // Resolve `$crate`s in the fragment for pretty-printing.
540565 self . cx . resolver . resolve_dollar_crates ( ) ;
541566
@@ -635,13 +660,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
635660 self . cx . trace_macros_diag ( ) ;
636661 }
637662
638- fn expand_invoc ( & mut self , invoc : Invocation , ext : & SyntaxExtensionKind ) -> AstFragment {
663+ fn expand_invoc (
664+ & mut self ,
665+ invoc : Invocation ,
666+ ext : & SyntaxExtensionKind ,
667+ ) -> ExpandResult < AstFragment , Invocation > {
639668 if self . cx . current_expansion . depth > self . cx . ecfg . recursion_limit {
640669 self . error_recursion_limit_reached ( ) ;
641670 }
642671
643672 let ( fragment_kind, span) = ( invoc. fragment_kind , invoc. span ( ) ) ;
644- match invoc. kind {
673+ ExpandResult :: Ready ( match invoc. kind {
645674 InvocationKind :: Bang { mac, .. } => match ext {
646675 SyntaxExtensionKind :: Bang ( expander) => {
647676 self . gate_proc_macro_expansion_kind ( span, fragment_kind) ;
@@ -663,7 +692,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
663692 }
664693 _ => unreachable ! ( ) ,
665694 } ,
666- InvocationKind :: Attr { attr, mut item, .. } => match ext {
695+ InvocationKind :: Attr { attr, mut item, derives , after_derive } => match ext {
667696 SyntaxExtensionKind :: Attr ( expander) => {
668697 self . gate_proc_macro_input ( & item) ;
669698 self . gate_proc_macro_attr_item ( span, & item) ;
@@ -679,8 +708,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
679708 SyntaxExtensionKind :: LegacyAttr ( expander) => {
680709 match validate_attr:: parse_meta ( self . cx . parse_sess , & attr) {
681710 Ok ( meta) => {
682- let item = expander. expand ( self . cx , span, & meta, item) ;
683- fragment_kind. expect_from_annotatables ( item)
711+ let items = match expander. expand ( self . cx , span, & meta, item) {
712+ ExpandResult :: Ready ( items) => items,
713+ ExpandResult :: Retry ( item, explanation) => {
714+ // Reassemble the original invocation for retrying.
715+ return ExpandResult :: Retry (
716+ Invocation {
717+ kind : InvocationKind :: Attr {
718+ attr,
719+ item,
720+ derives,
721+ after_derive,
722+ } ,
723+ ..invoc
724+ } ,
725+ explanation,
726+ ) ;
727+ }
728+ } ;
729+ fragment_kind. expect_from_annotatables ( items)
684730 }
685731 Err ( mut err) => {
686732 err. emit ( ) ;
@@ -702,19 +748,31 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
702748 SyntaxExtensionKind :: Derive ( expander)
703749 | SyntaxExtensionKind :: LegacyDerive ( expander) => {
704750 if !item. derive_allowed ( ) {
705- return fragment_kind. dummy ( span) ;
751+ return ExpandResult :: Ready ( fragment_kind. dummy ( span) ) ;
706752 }
707753 if let SyntaxExtensionKind :: Derive ( ..) = ext {
708754 self . gate_proc_macro_input ( & item) ;
709755 }
710756 let meta = ast:: MetaItem { kind : ast:: MetaItemKind :: Word , span, path } ;
711- let items = expander. expand ( self . cx , span, & meta, item) ;
757+ let items = match expander. expand ( self . cx , span, & meta, item) {
758+ ExpandResult :: Ready ( items) => items,
759+ ExpandResult :: Retry ( item, explanation) => {
760+ // Reassemble the original invocation for retrying.
761+ return ExpandResult :: Retry (
762+ Invocation {
763+ kind : InvocationKind :: Derive { path : meta. path , item } ,
764+ ..invoc
765+ } ,
766+ explanation,
767+ ) ;
768+ }
769+ } ;
712770 fragment_kind. expect_from_annotatables ( items)
713771 }
714772 _ => unreachable ! ( ) ,
715773 } ,
716774 InvocationKind :: DeriveContainer { .. } => unreachable ! ( ) ,
717- }
775+ } )
718776 }
719777
720778 fn gate_proc_macro_attr_item ( & self , span : Span , item : & Annotatable ) {
@@ -933,7 +991,7 @@ pub fn ensure_complete_parse<'a>(
933991struct InvocationCollector < ' a , ' b > {
934992 cx : & ' a mut ExtCtxt < ' b > ,
935993 cfg : StripUnconfigured < ' a > ,
936- invocations : Vec < Invocation > ,
994+ invocations : Vec < ( Invocation , Option < InvocationRes > ) > ,
937995 monotonic : bool ,
938996}
939997
@@ -955,15 +1013,18 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
9551013 } ;
9561014 let expn_id = ExpnId :: fresh ( expn_data) ;
9571015 let vis = kind. placeholder_visibility ( ) ;
958- self . invocations . push ( Invocation {
959- kind,
960- fragment_kind,
961- expansion_data : ExpansionData {
962- id : expn_id,
963- depth : self . cx . current_expansion . depth + 1 ,
964- ..self . cx . current_expansion . clone ( )
1016+ self . invocations . push ( (
1017+ Invocation {
1018+ kind,
1019+ fragment_kind,
1020+ expansion_data : ExpansionData {
1021+ id : expn_id,
1022+ depth : self . cx . current_expansion . depth + 1 ,
1023+ ..self . cx . current_expansion . clone ( )
1024+ } ,
9651025 } ,
966- } ) ;
1026+ None ,
1027+ ) ) ;
9671028 placeholder ( fragment_kind, NodeId :: placeholder_from_expn_id ( expn_id) , vis)
9681029 }
9691030
0 commit comments