@@ -71,11 +71,10 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan};
7171use errors:: { Applicability , DiagnosticBuilder , DiagnosticId } ;
7272
7373use std:: cell:: { Cell , RefCell } ;
74- use std:: cmp;
74+ use std:: { cmp, fmt , iter , ptr } ;
7575use std:: collections:: BTreeSet ;
76- use std:: fmt;
77- use std:: iter;
7876use std:: mem:: replace;
77+ use rustc_data_structures:: ptr_key:: PtrKey ;
7978use rustc_data_structures:: sync:: Lrc ;
8079
8180use resolve_imports:: { ImportDirective , ImportDirectiveSubclass , NameResolution , ImportResolver } ;
@@ -1113,6 +1112,17 @@ impl<'a> ModuleData<'a> {
11131112 fn nearest_item_scope ( & ' a self ) -> Module < ' a > {
11141113 if self . is_trait ( ) { self . parent . unwrap ( ) } else { self }
11151114 }
1115+
1116+ fn is_ancestor_of ( & self , mut other : & Self ) -> bool {
1117+ while !ptr:: eq ( self , other) {
1118+ if let Some ( parent) = other. parent {
1119+ other = parent;
1120+ } else {
1121+ return false ;
1122+ }
1123+ }
1124+ true
1125+ }
11161126}
11171127
11181128impl < ' a > fmt:: Debug for ModuleData < ' a > {
@@ -1407,6 +1417,7 @@ pub struct Resolver<'a, 'b: 'a> {
14071417 block_map : NodeMap < Module < ' a > > ,
14081418 module_map : FxHashMap < DefId , Module < ' a > > ,
14091419 extern_module_map : FxHashMap < ( DefId , bool /* MacrosOnly? */ ) , Module < ' a > > ,
1420+ binding_parent_modules : FxHashMap < PtrKey < ' a , NameBinding < ' a > > , Module < ' a > > ,
14101421
14111422 pub make_glob_map : bool ,
14121423 /// Maps imports to the names of items actually imported (this actually maps
@@ -1709,6 +1720,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
17091720 module_map,
17101721 block_map : NodeMap ( ) ,
17111722 extern_module_map : FxHashMap ( ) ,
1723+ binding_parent_modules : FxHashMap ( ) ,
17121724
17131725 make_glob_map : make_glob_map == MakeGlobMap :: Yes ,
17141726 glob_map : NodeMap ( ) ,
@@ -4526,6 +4538,31 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
45264538 vis. is_accessible_from ( module. normal_ancestor_id , self )
45274539 }
45284540
4541+ fn set_binding_parent_module ( & mut self , binding : & ' a NameBinding < ' a > , module : Module < ' a > ) {
4542+ if let Some ( old_module) = self . binding_parent_modules . insert ( PtrKey ( binding) , module) {
4543+ if !ptr:: eq ( module, old_module) {
4544+ span_bug ! ( binding. span, "parent module is reset for binding" ) ;
4545+ }
4546+ }
4547+ }
4548+
4549+ fn disambiguate_legacy_vs_modern (
4550+ & self ,
4551+ legacy : & ' a NameBinding < ' a > ,
4552+ modern : & ' a NameBinding < ' a > ,
4553+ ) -> bool {
4554+ // Some non-controversial subset of ambiguities "modern macro name" vs "macro_rules"
4555+ // is disambiguated to mitigate regressions from macro modularization.
4556+ // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general.
4557+ match ( self . binding_parent_modules . get ( & PtrKey ( legacy) ) ,
4558+ self . binding_parent_modules . get ( & PtrKey ( modern) ) ) {
4559+ ( Some ( legacy) , Some ( modern) ) =>
4560+ legacy. normal_ancestor_id == modern. normal_ancestor_id &&
4561+ modern. is_ancestor_of ( legacy) ,
4562+ _ => false ,
4563+ }
4564+ }
4565+
45294566 fn report_ambiguity_error ( & self , ident : Ident , b1 : & NameBinding , b2 : & NameBinding ) {
45304567 let participle = |is_import : bool | if is_import { "imported" } else { "defined" } ;
45314568 let msg1 =
0 commit comments