@@ -107,6 +107,14 @@ impl<'a> MacroBinding<'a> {
107107 MacroBinding :: Legacy ( _) => panic ! ( "unexpected MacroBinding::Legacy" ) ,
108108 }
109109 }
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+ }
110118}
111119
112120impl < ' a > base:: Resolver for Resolver < ' a > {
@@ -476,7 +484,7 @@ impl<'a> Resolver<'a> {
476484 } ;
477485
478486 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 ( ) ) ) ;
480488
481489 result
482490 }
@@ -622,10 +630,33 @@ impl<'a> Resolver<'a> {
622630 }
623631 }
624632
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 ;
626635 let legacy_scope = & self . invocations [ & mark] . legacy_scope ;
627636 let legacy_resolution = self . resolve_legacy_scope ( legacy_scope, ident, true ) ;
628637 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+
629660 match ( legacy_resolution, resolution) {
630661 ( Some ( MacroBinding :: Legacy ( legacy_binding) ) , Ok ( MacroBinding :: Modern ( binding) ) ) => {
631662 let msg1 = format ! ( "`{}` could refer to the macro defined here" , ident) ;
@@ -635,24 +666,35 @@ impl<'a> Resolver<'a> {
635666 . span_note ( binding. span , & msg2)
636667 . emit ( ) ;
637668 } ,
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- } ,
642669 ( 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) ;
651674 let mut err = self . session . struct_span_err ( span, & msg) ;
652675 self . suggest_macro_name ( & ident. as_str ( ) , kind, & mut err, span) ;
653676 err. emit ( ) ;
654677 } ,
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+ } ,
656698 } ;
657699 }
658700 }
0 commit comments