@@ -107,6 +107,14 @@ impl<'a> MacroBinding<'a> {
107
107
MacroBinding :: Legacy ( _) => panic ! ( "unexpected MacroBinding::Legacy" ) ,
108
108
}
109
109
}
110
+
111
+ pub fn def_ignoring_ambiguity ( self ) -> Def {
112
+ match self {
113
+ MacroBinding :: Legacy ( binding) => Def :: Macro ( binding. def_id , MacroKind :: Bang ) ,
114
+ MacroBinding :: Global ( binding) | MacroBinding :: Modern ( binding) =>
115
+ binding. def_ignoring_ambiguity ( ) ,
116
+ }
117
+ }
110
118
}
111
119
112
120
impl < ' a > base:: Resolver for Resolver < ' a > {
@@ -476,7 +484,7 @@ impl<'a> Resolver<'a> {
476
484
} ;
477
485
478
486
self . current_module . nearest_item_scope ( ) . legacy_macro_resolutions . borrow_mut ( )
479
- . push ( ( scope, path[ 0 ] , span , kind ) ) ;
487
+ . push ( ( scope, path[ 0 ] , kind , result . ok ( ) ) ) ;
480
488
481
489
result
482
490
}
@@ -622,10 +630,33 @@ impl<'a> Resolver<'a> {
622
630
}
623
631
}
624
632
625
- for & ( mark, ident, span, kind) in module. legacy_macro_resolutions . borrow ( ) . iter ( ) {
633
+ for & ( mark, ident, kind, def) in module. legacy_macro_resolutions . borrow ( ) . iter ( ) {
634
+ let span = ident. span ;
626
635
let legacy_scope = & self . invocations [ & mark] . legacy_scope ;
627
636
let legacy_resolution = self . resolve_legacy_scope ( legacy_scope, ident, true ) ;
628
637
let resolution = self . resolve_lexical_macro_path_segment ( ident, MacroNS , true , span) ;
638
+
639
+ let check_consistency = |this : & Self , binding : MacroBinding | {
640
+ if let Some ( def) = def {
641
+ if this. ambiguity_errors . is_empty ( ) && this. disallowed_shadowing . is_empty ( ) &&
642
+ binding. def_ignoring_ambiguity ( ) != def {
643
+ // Make sure compilation does not succeed if preferred macro resolution
644
+ // has changed after the macro had been expanded. In theory all such
645
+ // situations should be reported as ambiguity errors, so this is span-bug.
646
+ span_bug ! ( span, "inconsistent resolution for a macro" ) ;
647
+ }
648
+ } else {
649
+ // It's possible that the macro was unresolved (indeterminate) and silently
650
+ // expanded into a dummy fragment for recovery during expansion.
651
+ // Now, post-expansion, the resolution may succeed, but we can't change the
652
+ // past and need to report an error.
653
+ let msg =
654
+ format ! ( "cannot determine resolution for the {} `{}`" , kind. descr( ) , ident) ;
655
+ let msg_note = "import resolution is stuck, try simplifying macro imports" ;
656
+ this. session . struct_span_err ( span, & msg) . note ( msg_note) . emit ( ) ;
657
+ }
658
+ } ;
659
+
629
660
match ( legacy_resolution, resolution) {
630
661
( Some ( MacroBinding :: Legacy ( legacy_binding) ) , Ok ( MacroBinding :: Modern ( binding) ) ) => {
631
662
let msg1 = format ! ( "`{}` could refer to the macro defined here" , ident) ;
@@ -635,24 +666,35 @@ impl<'a> Resolver<'a> {
635
666
. span_note ( binding. span , & msg2)
636
667
. emit ( ) ;
637
668
} ,
638
- ( Some ( MacroBinding :: Global ( binding) ) , Ok ( MacroBinding :: Global ( _) ) ) => {
639
- self . record_use ( ident, MacroNS , binding, span) ;
640
- self . err_if_macro_use_proc_macro ( ident. name , span, binding) ;
641
- } ,
642
669
( None , Err ( _) ) => {
643
- let msg = match kind {
644
- MacroKind :: Bang =>
645
- format ! ( "cannot find macro `{}!` in this scope" , ident) ,
646
- MacroKind :: Attr =>
647
- format ! ( "cannot find attribute macro `{}` in this scope" , ident) ,
648
- MacroKind :: Derive =>
649
- format ! ( "cannot find derive macro `{}` in this scope" , ident) ,
650
- } ;
670
+ assert ! ( def. is_none( ) ) ;
671
+ let bang = if kind == MacroKind :: Bang { "!" } else { "" } ;
672
+ let msg =
673
+ format ! ( "cannot find {} `{}{}` in this scope" , kind. descr( ) , ident, bang) ;
651
674
let mut err = self . session . struct_span_err ( span, & msg) ;
652
675
self . suggest_macro_name ( & ident. as_str ( ) , kind, & mut err, span) ;
653
676
err. emit ( ) ;
654
677
} ,
655
- _ => { } ,
678
+ ( Some ( MacroBinding :: Modern ( _) ) , _) | ( _, Ok ( MacroBinding :: Legacy ( _) ) ) => {
679
+ span_bug ! ( span, "impossible macro resolution result" ) ;
680
+ }
681
+ // OK, unambiguous resolution
682
+ ( Some ( binding) , Err ( _) ) | ( None , Ok ( binding) ) |
683
+ // OK, legacy wins over global even if their definitions are different
684
+ ( Some ( binding @ MacroBinding :: Legacy ( _) ) , Ok ( MacroBinding :: Global ( _) ) ) |
685
+ // OK, modern wins over global even if their definitions are different
686
+ ( Some ( MacroBinding :: Global ( _) ) , Ok ( binding @ MacroBinding :: Modern ( _) ) ) => {
687
+ check_consistency ( self , binding) ;
688
+ }
689
+ ( Some ( MacroBinding :: Global ( binding1) ) , Ok ( MacroBinding :: Global ( binding2) ) ) => {
690
+ if binding1. def ( ) != binding2. def ( ) {
691
+ span_bug ! ( span, "mismatch between same global macro resolutions" ) ;
692
+ }
693
+ check_consistency ( self , MacroBinding :: Global ( binding1) ) ;
694
+
695
+ self . record_use ( ident, MacroNS , binding1, span) ;
696
+ self . err_if_macro_use_proc_macro ( ident. name , span, binding1) ;
697
+ } ,
656
698
} ;
657
699
}
658
700
}
0 commit comments