@@ -5,7 +5,7 @@ use std::mem;
55use std:: ops:: Deref ;
66
77use rustc_ast:: NodeId ;
8- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
8+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
99use rustc_data_structures:: intern:: Interned ;
1010use rustc_errors:: codes:: * ;
1111use rustc_errors:: { Applicability , MultiSpan , pluralize, struct_span_code_err} ;
@@ -47,59 +47,89 @@ struct ImportResolver<'r, 'ra, 'tcx> {
4747 outputs : ImportResolutionOutputs < ' ra > ,
4848}
4949
50+ enum SideEffect < ' ra > {
51+ None ,
52+ Prelude ,
53+ Single {
54+ parent : Module < ' ra > ,
55+ import_bindings : PerNS < PendingBinding < ' ra > > ,
56+ } ,
57+ Glob {
58+ parent : Module < ' ra > ,
59+ import_bindings : Vec < ( NameBinding < ' ra > , BindingKey , bool /* warn_ambiguity */ ) > ,
60+ path_res : PartialRes ,
61+ } ,
62+ }
63+
5064#[ derive( Default ) ]
5165struct ImportResolutionOutputs < ' ra > {
52- prelude : Option < Module < ' ra > > ,
5366 indeterminate_imports : Vec < Import < ' ra > > ,
54- determined_imports : Vec < Import < ' ra > > ,
55- module_glob_importers : FxIndexMap < Module < ' ra > , Vec < Import < ' ra > > > ,
56- glob_import_bindings :
57- Vec < ( Module < ' ra > , BindingKey , NameBinding < ' ra > , bool /* warn_ambiguity */ ) > ,
58- glob_path_res : Vec < ( NodeId , PartialRes ) > ,
59- single_import_bindings : PerNS < Vec < ( Module < ' ra > , Import < ' ra > , PendingBinding < ' ra > ) > > ,
67+ determined_imports : Vec < ( Import < ' ra > , SideEffect < ' ra > ) > ,
6068}
6169
6270impl < ' ra > ImportResolutionOutputs < ' ra > {
6371 fn commit < ' tcx > ( self , r : & mut Resolver < ' ra , ' tcx > ) {
6472 r. indeterminate_imports = self . indeterminate_imports ;
65- r. determined_imports . extend ( self . determined_imports ) ;
66-
67- // It's possible this particular round didn't set the prelude, so we should not
68- // unset it in the main resolver.
69- if self . prelude . is_some ( ) {
70- r. prelude = self . prelude ;
71- }
72-
73- for ( module, glob_importers) in self . module_glob_importers {
74- module. glob_importers . borrow_mut ( ) . extend ( glob_importers) ;
75- }
76-
77- for ( module, key, binding, warn_ambiguity) in self . glob_import_bindings {
78- let _ = r. try_define_local ( module, key. ident . 0 , key. ns , binding, warn_ambiguity) ;
79- }
73+ r. determined_imports . reserve ( self . determined_imports . len ( ) ) ;
74+
75+ for ( import, side_effect) in self . determined_imports {
76+ r. determined_imports . push ( import) ;
77+
78+ match ( & import. kind , side_effect) {
79+ (
80+ ImportKind :: Single { target, bindings, .. } ,
81+ SideEffect :: Single { parent, import_bindings } ,
82+ ) => {
83+ for ( ns, pending_binding) in import_bindings. into_iter_with ( ) {
84+ match pending_binding {
85+ PendingBinding :: Ready ( Some ( binding) ) => {
86+ r. define_binding_local ( parent, * target, ns, binding) ;
87+ }
88+ PendingBinding :: Ready ( None ) => {
89+ let key = BindingKey :: new ( * target, ns) ;
90+ r. update_local_resolution ( parent, key, false , |_, resolution| {
91+ resolution. single_imports . swap_remove ( & import) ;
92+ } ) ;
93+ }
94+ _ => { }
95+ }
96+ bindings[ ns] . set ( pending_binding) ;
97+ }
98+ }
99+ (
100+ ImportKind :: Glob { id, .. } ,
101+ SideEffect :: Glob { parent, import_bindings, path_res } ,
102+ ) => {
103+ let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( )
104+ else {
105+ unreachable ! ( ) ;
106+ } ;
80107
81- for ( id, res) in self . glob_path_res {
82- r. record_partial_res ( id, res) ;
83- }
108+ module. glob_importers . borrow_mut ( ) . push ( import) ;
84109
85- for ( ns, import_bindings) in self . single_import_bindings . into_iter_with ( ) {
86- for ( parent, import, pending_binding) in import_bindings {
87- let ImportKind :: Single { target, ref bindings, .. } = import. kind else {
88- unreachable ! ( ) ;
89- } ;
90- match pending_binding {
91- PendingBinding :: Ready ( Some ( binding) ) => {
92- r. define_binding_local ( parent, target, ns, binding) ;
93- }
94- PendingBinding :: Ready ( None ) => {
95- let key = BindingKey :: new ( target, ns) ;
96- r. update_local_resolution ( parent, key, false , |_, resolution| {
97- resolution. single_imports . swap_remove ( & import) ;
98- } ) ;
110+ for ( binding, key, warn_ambiguity) in import_bindings {
111+ let _ = r. try_define_local (
112+ parent,
113+ key. ident . 0 ,
114+ key. ns ,
115+ binding,
116+ warn_ambiguity,
117+ ) ;
99118 }
100- _ => { }
119+
120+ r. record_partial_res ( * id, path_res) ;
101121 }
102- bindings[ ns] . set ( pending_binding) ;
122+ ( ImportKind :: Glob { is_prelude : true , .. } , SideEffect :: Prelude ) => {
123+ let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( )
124+ else {
125+ unreachable ! ( )
126+ } ;
127+ r. prelude = Some ( module) ;
128+ }
129+
130+ ( _, SideEffect :: None ) => { }
131+ // Something weird happened, which shouldn't have happened.
132+ _ => unreachable ! ( "Mismatched import kind and side effect" ) ,
103133 }
104134 }
105135 }
@@ -650,10 +680,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
650680 ) -> ( ImportResolutionOutputs < ' ra > , usize ) {
651681 let mut indeterminate_count = 0 ;
652682 for import in batch {
653- let import_indeterminate_count = self . resolve_import ( import) ;
683+ let ( side_effect , import_indeterminate_count) = self . resolve_import ( import) ;
654684 indeterminate_count += import_indeterminate_count;
655685 match import_indeterminate_count {
656- 0 => self . outputs . determined_imports . push ( import) ,
686+ 0 => self . outputs . determined_imports . push ( ( import, side_effect ) ) ,
657687 _ => self . outputs . indeterminate_imports . push ( import) ,
658688 }
659689 }
@@ -930,7 +960,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
930960 ///
931961 /// Meanwhile, if resolve successful, the resolved bindings are written
932962 /// into the module.
933- fn resolve_import < ' r > ( self : & mut ImportResolver < ' r , ' ra , ' tcx > , import : Import < ' ra > ) -> usize {
963+ fn resolve_import < ' r > (
964+ self : & mut ImportResolver < ' r , ' ra , ' tcx > ,
965+ import : Import < ' ra > ,
966+ ) -> ( SideEffect < ' ra > , usize ) {
934967 debug ! (
935968 "(resolving import for module) resolving import `{}::{}` in `{}`" ,
936969 Segment :: names_to_string( & import. module_path) ,
@@ -949,8 +982,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
949982
950983 match path_res {
951984 PathResult :: Module ( module) => module,
952- PathResult :: Indeterminate => return 3 ,
953- PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => return 0 ,
985+ PathResult :: Indeterminate => return ( SideEffect :: None , 3 ) ,
986+ PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => {
987+ return ( SideEffect :: None , 0 ) ;
988+ }
954989 }
955990 } ;
956991
@@ -960,12 +995,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
960995 ( source, target, bindings, type_ns_only)
961996 }
962997 ImportKind :: Glob { .. } => {
963- self . resolve_glob_import ( import) ;
964- return 0 ;
998+ return ( self . resolve_glob_import ( import) , 0 ) ;
965999 }
9661000 _ => unreachable ! ( ) ,
9671001 } ;
9681002
1003+ let mut import_bindings = PerNS :: default ( ) ;
9691004 let mut indeterminate_count = 0 ;
9701005 self . r . reborrow ( ) . per_ns_cm ( |this, ns| {
9711006 if !type_ns_only || ns == TypeNS {
@@ -979,7 +1014,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9791014 & import. parent_scope ,
9801015 Some ( import) ,
9811016 ) ;
982- let parent = import. parent_scope . module ;
9831017 let pending_binding = match binding_result {
9841018 Ok ( binding) => {
9851019 if binding. is_assoc_item ( )
@@ -1009,11 +1043,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10091043 return ;
10101044 }
10111045 } ;
1012- self . outputs . single_import_bindings [ ns] . push ( ( parent , import , pending_binding) ) ;
1046+ import_bindings [ ns] = pending_binding;
10131047 }
10141048 } ) ;
10151049
1016- indeterminate_count
1050+ (
1051+ SideEffect :: Single { parent : import. parent_scope . module , import_bindings } ,
1052+ indeterminate_count,
1053+ )
10171054 }
10181055
10191056 /// Performs final import resolution, consistency checks and error reporting.
@@ -1554,13 +1591,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15541591 false
15551592 }
15561593
1557- fn resolve_glob_import < ' r > ( self : & mut ImportResolver < ' r , ' ra , ' tcx > , import : Import < ' ra > ) {
1594+ fn resolve_glob_import < ' r > (
1595+ self : & mut ImportResolver < ' r , ' ra , ' tcx > ,
1596+ import : Import < ' ra > ,
1597+ ) -> SideEffect < ' ra > {
15581598 // This function is only called for glob imports.
1559- let ImportKind :: Glob { id , is_prelude, .. } = import. kind else { unreachable ! ( ) } ;
1599+ let ImportKind :: Glob { is_prelude, .. } = import. kind else { unreachable ! ( ) } ;
15601600
15611601 let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( ) else {
15621602 self . dcx ( ) . emit_err ( CannotGlobImportAllCrates { span : import. span } ) ;
1563- return ;
1603+ return SideEffect :: None ;
15641604 } ;
15651605
15661606 if module. is_trait ( ) && !self . tcx . features ( ) . import_trait_associated_functions ( ) {
@@ -1574,15 +1614,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15741614 }
15751615
15761616 if module == import. parent_scope . module {
1577- return ;
1617+ return SideEffect :: None ;
15781618 } else if is_prelude {
1579- self . outputs . prelude = Some ( module) ;
1580- return ;
1619+ return SideEffect :: Prelude ;
15811620 }
15821621
1583- // Add to module's glob_importers
1584- self . outputs . module_glob_importers . entry ( module) . or_default ( ) . push ( import) ;
1585-
15861622 // Ensure that `resolutions` isn't borrowed during `try_define`,
15871623 // since it might get updated via a glob cycle.
15881624 let bindings = self
@@ -1593,6 +1629,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15931629 resolution. borrow ( ) . binding ( ) . map ( |binding| ( * key, binding) )
15941630 } )
15951631 . collect :: < Vec < _ > > ( ) ;
1632+ let mut import_bindings = Vec :: with_capacity ( bindings. len ( ) ) ;
15961633 for ( mut key, binding) in bindings {
15971634 let scope = match key. ident . 0 . span . reverse_glob_adjust ( module. expansion , import. span ) {
15981635 Some ( Some ( def) ) => self . expn_def_scope ( def) ,
@@ -1605,17 +1642,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16051642 . resolution ( import. parent_scope . module , key)
16061643 . and_then ( |r| r. binding ( ) )
16071644 . is_some_and ( |binding| binding. warn_ambiguity_recursive ( ) ) ;
1608- self . outputs . glob_import_bindings . push ( (
1609- import. parent_scope . module ,
1610- key,
1611- imported_binding,
1612- warn_ambiguity,
1613- ) ) ;
1645+ import_bindings. push ( ( imported_binding, key, warn_ambiguity) ) ;
16141646 }
16151647 }
16161648
16171649 // Record the destination of this import
1618- self . outputs . glob_path_res . push ( ( id, PartialRes :: new ( module. res ( ) . unwrap ( ) ) ) ) ;
1650+ SideEffect :: Glob {
1651+ parent : import. parent_scope . module ,
1652+ import_bindings,
1653+ path_res : PartialRes :: new ( module. res ( ) . unwrap ( ) ) ,
1654+ }
16191655 }
16201656
16211657 // Miscellaneous post-processing, including recording re-exports,
0 commit comments