@@ -408,7 +408,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
408
408
let mut undetermined_invocations = Vec :: new ( ) ;
409
409
let ( mut progress, mut force) = ( false , !self . monotonic ) ;
410
410
loop {
411
- let invoc = if let Some ( invoc) = invocations. pop ( ) {
411
+ let ( invoc, res ) = if let Some ( invoc) = invocations. pop ( ) {
412
412
invoc
413
413
} else {
414
414
self . resolve_imports ( ) ;
@@ -420,30 +420,51 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
420
420
continue ;
421
421
} ;
422
422
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
+ }
434
443
}
435
444
} ;
436
445
437
- progress = true ;
438
446
let ExpansionData { depth, id : expn_id, .. } = invoc. expansion_data ;
439
447
self . cx . current_expansion = invoc. expansion_data . clone ( ) ;
440
448
441
449
// FIXME(jseyfried): Refactor out the following logic
442
450
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
+ } ,
447
468
InvocationRes :: DeriveContainer ( _exts) => {
448
469
// FIXME: Consider using the derive resolutions (`_exts`) immediately,
449
470
// instead of enqueuing the derives to be resolved again later.
@@ -463,21 +484,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
463
484
for path in derives {
464
485
let expn_id = ExpnId :: fresh ( None ) ;
465
486
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
+ } ,
472
495
} ,
473
- } ) ;
496
+ None ,
497
+ ) ) ;
474
498
}
475
499
let fragment =
476
500
invoc. fragment_kind . expect_from_annotatables ( :: std:: iter:: once ( item) ) ;
477
501
self . collect_invocations ( fragment, & derive_placeholders)
478
502
}
479
503
} ;
480
504
505
+ progress = true ;
481
506
if expanded_fragments. len ( ) < depth {
482
507
expanded_fragments. push ( Vec :: new ( ) ) ;
483
508
}
@@ -535,7 +560,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
535
560
& mut self ,
536
561
mut fragment : AstFragment ,
537
562
extra_placeholders : & [ NodeId ] ,
538
- ) -> ( AstFragment , Vec < Invocation > ) {
563
+ ) -> ( AstFragment , Vec < ( Invocation , Option < InvocationRes > ) > ) {
539
564
// Resolve `$crate`s in the fragment for pretty-printing.
540
565
self . cx . resolver . resolve_dollar_crates ( ) ;
541
566
@@ -635,13 +660,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
635
660
self . cx . trace_macros_diag ( ) ;
636
661
}
637
662
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 > {
639
668
if self . cx . current_expansion . depth > self . cx . ecfg . recursion_limit {
640
669
self . error_recursion_limit_reached ( ) ;
641
670
}
642
671
643
672
let ( fragment_kind, span) = ( invoc. fragment_kind , invoc. span ( ) ) ;
644
- match invoc. kind {
673
+ ExpandResult :: Ready ( match invoc. kind {
645
674
InvocationKind :: Bang { mac, .. } => match ext {
646
675
SyntaxExtensionKind :: Bang ( expander) => {
647
676
self . gate_proc_macro_expansion_kind ( span, fragment_kind) ;
@@ -663,7 +692,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
663
692
}
664
693
_ => unreachable ! ( ) ,
665
694
} ,
666
- InvocationKind :: Attr { attr, mut item, .. } => match ext {
695
+ InvocationKind :: Attr { attr, mut item, derives , after_derive } => match ext {
667
696
SyntaxExtensionKind :: Attr ( expander) => {
668
697
self . gate_proc_macro_input ( & item) ;
669
698
self . gate_proc_macro_attr_item ( span, & item) ;
@@ -679,8 +708,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
679
708
SyntaxExtensionKind :: LegacyAttr ( expander) => {
680
709
match validate_attr:: parse_meta ( self . cx . parse_sess , & attr) {
681
710
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)
684
730
}
685
731
Err ( mut err) => {
686
732
err. emit ( ) ;
@@ -702,19 +748,31 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
702
748
SyntaxExtensionKind :: Derive ( expander)
703
749
| SyntaxExtensionKind :: LegacyDerive ( expander) => {
704
750
if !item. derive_allowed ( ) {
705
- return fragment_kind. dummy ( span) ;
751
+ return ExpandResult :: Ready ( fragment_kind. dummy ( span) ) ;
706
752
}
707
753
if let SyntaxExtensionKind :: Derive ( ..) = ext {
708
754
self . gate_proc_macro_input ( & item) ;
709
755
}
710
756
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
+ } ;
712
770
fragment_kind. expect_from_annotatables ( items)
713
771
}
714
772
_ => unreachable ! ( ) ,
715
773
} ,
716
774
InvocationKind :: DeriveContainer { .. } => unreachable ! ( ) ,
717
- }
775
+ } )
718
776
}
719
777
720
778
fn gate_proc_macro_attr_item ( & self , span : Span , item : & Annotatable ) {
@@ -933,7 +991,7 @@ pub fn ensure_complete_parse<'a>(
933
991
struct InvocationCollector < ' a , ' b > {
934
992
cx : & ' a mut ExtCtxt < ' b > ,
935
993
cfg : StripUnconfigured < ' a > ,
936
- invocations : Vec < Invocation > ,
994
+ invocations : Vec < ( Invocation , Option < InvocationRes > ) > ,
937
995
monotonic : bool ,
938
996
}
939
997
@@ -955,15 +1013,18 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
955
1013
} ;
956
1014
let expn_id = ExpnId :: fresh ( expn_data) ;
957
1015
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
+ } ,
965
1025
} ,
966
- } ) ;
1026
+ None ,
1027
+ ) ) ;
967
1028
placeholder ( fragment_kind, NodeId :: placeholder_from_expn_id ( expn_id) , vis)
968
1029
}
969
1030
0 commit comments