11//! A bunch of methods and structures more or less related to resolving imports.
22
33use std:: mem;
4+ use std:: ops:: Deref ;
45
56use rustc_ast:: NodeId ;
67use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
@@ -41,6 +42,96 @@ use crate::{
4142
4243type Res = def:: Res < NodeId > ;
4344
45+ struct ImportResolver < ' r , ' ra , ' tcx > {
46+ r : CmResolver < ' r , ' ra , ' tcx > , // always immutable
47+ outputs : ImportResolutionOutputs < ' ra > ,
48+ }
49+
50+ enum SideEffect < ' ra > {
51+ None ,
52+ Single { import_bindings : PerNS < PendingBinding < ' ra > > } ,
53+ Glob { import_bindings : Vec < ( NameBinding < ' ra > , BindingKey , bool /* warn_ambiguity */ ) > } ,
54+ }
55+
56+ #[ derive( Default ) ]
57+ struct ImportResolutionOutputs < ' ra > {
58+ indeterminate_imports : Vec < Import < ' ra > > ,
59+ determined_imports : Vec < ( Import < ' ra > , SideEffect < ' ra > ) > ,
60+ }
61+
62+ impl < ' ra > ImportResolutionOutputs < ' ra > {
63+ fn commit < ' tcx > ( self , r : & mut Resolver < ' ra , ' tcx > ) {
64+ r. indeterminate_imports = self . indeterminate_imports ;
65+ r. determined_imports . reserve ( self . determined_imports . len ( ) ) ;
66+
67+ for ( import, side_effect) in self . determined_imports {
68+ r. determined_imports . push ( import) ;
69+
70+ let parent = import. parent_scope . module ;
71+ match ( & import. kind , side_effect) {
72+ (
73+ ImportKind :: Single { target, bindings, .. } ,
74+ SideEffect :: Single { import_bindings } ,
75+ ) => {
76+ for ( ns, pending_binding) in import_bindings. into_iter_with ( ) {
77+ match pending_binding {
78+ PendingBinding :: Ready ( Some ( binding) ) => {
79+ r. define_binding_local ( parent, * target, ns, binding) ;
80+ }
81+ PendingBinding :: Ready ( None ) => {
82+ let key = BindingKey :: new ( * target, ns) ;
83+ r. update_local_resolution ( parent, key, false , |_, resolution| {
84+ resolution. single_imports . swap_remove ( & import) ;
85+ } ) ;
86+ }
87+ _ => { }
88+ }
89+ bindings[ ns] . set ( pending_binding) ;
90+ }
91+ }
92+ ( ImportKind :: Glob { id, .. } , SideEffect :: Glob { import_bindings } ) => {
93+ let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( )
94+ else {
95+ unreachable ! ( ) ;
96+ } ;
97+
98+ module. glob_importers . borrow_mut ( r) . push ( import) ;
99+
100+ for ( binding, key, warn_ambiguity) in import_bindings {
101+ let _ = r. try_define_local (
102+ parent,
103+ key. ident . 0 ,
104+ key. ns ,
105+ binding,
106+ warn_ambiguity,
107+ ) ;
108+ }
109+
110+ r. record_partial_res ( * id, PartialRes :: new ( module. res ( ) . unwrap ( ) ) ) ;
111+ }
112+
113+ ( _, SideEffect :: None ) => { }
114+ // Something weird happened, which shouldn't have happened.
115+ _ => unreachable ! ( "Mismatched import kind and side effect" ) ,
116+ }
117+ }
118+ }
119+ }
120+
121+ impl < ' r , ' ra , ' tcx > Deref for ImportResolver < ' r , ' ra , ' tcx > {
122+ type Target = Resolver < ' ra , ' tcx > ;
123+
124+ fn deref ( & self ) -> & Self :: Target {
125+ self . r . deref ( )
126+ }
127+ }
128+
129+ impl < ' r , ' ra , ' tcx > AsRef < Resolver < ' ra , ' tcx > > for ImportResolver < ' r , ' ra , ' tcx > {
130+ fn as_ref ( & self ) -> & Resolver < ' ra , ' tcx > {
131+ self . r . as_ref ( )
132+ }
133+ }
134+
44135/// A [`NameBinding`] in the process of being resolved.
45136#[ derive( Clone , Copy , Default , PartialEq ) ]
46137pub ( crate ) enum PendingBinding < ' ra > {
@@ -555,18 +646,31 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
555646 let mut indeterminate_count = self . indeterminate_imports . len ( ) * 3 ;
556647 while indeterminate_count < prev_indeterminate_count {
557648 prev_indeterminate_count = indeterminate_count;
558- indeterminate_count = 0 ;
649+ let batch = mem :: take ( & mut self . indeterminate_imports ) ;
559650 self . assert_speculative = true ;
560- for import in mem:: take ( & mut self . indeterminate_imports ) {
561- let import_indeterminate_count = self . cm ( ) . resolve_import ( import) ;
562- indeterminate_count += import_indeterminate_count;
563- match import_indeterminate_count {
564- 0 => self . determined_imports . push ( import) ,
565- _ => self . indeterminate_imports . push ( import) ,
566- }
651+ let ( outputs, count) =
652+ ImportResolver { r : self . cm ( ) , outputs : Default :: default ( ) } . resolve_batch ( batch) ;
653+ self . assert_speculative = false ;
654+ indeterminate_count = count;
655+ outputs. commit ( self ) ;
656+ }
657+ }
658+
659+ fn resolve_batch < ' r > (
660+ mut self : ImportResolver < ' r , ' ra , ' tcx > ,
661+ batch : Vec < Import < ' ra > > ,
662+ ) -> ( ImportResolutionOutputs < ' ra > , usize ) {
663+ let mut indeterminate_count = 0 ;
664+ for import in batch {
665+ let ( side_effect, import_indeterminate_count) = self . resolve_import ( import) ;
666+ indeterminate_count += import_indeterminate_count;
667+ match import_indeterminate_count {
668+ 0 => self . outputs . determined_imports . push ( ( import, side_effect) ) ,
669+ _ => self . outputs . indeterminate_imports . push ( import) ,
567670 }
568671 self . assert_speculative = false ;
569672 }
673+ ( self . outputs , indeterminate_count)
570674 }
571675
572676 pub ( crate ) fn finalize_imports ( & mut self ) {
@@ -837,7 +941,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
837941 ///
838942 /// Meanwhile, if resolve successful, the resolved bindings are written
839943 /// into the module.
840- fn resolve_import < ' r > ( mut self : CmResolver < ' r , ' ra , ' tcx > , import : Import < ' ra > ) -> usize {
944+ fn resolve_import < ' r > (
945+ self : & mut ImportResolver < ' r , ' ra , ' tcx > ,
946+ import : Import < ' ra > ,
947+ ) -> ( SideEffect < ' ra > , usize ) {
841948 debug ! (
842949 "(resolving import for module) resolving import `{}::...` in `{}`" ,
843950 Segment :: names_to_string( & import. module_path) ,
@@ -846,7 +953,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
846953 let module = if let Some ( module) = import. imported_module . get ( ) {
847954 module
848955 } else {
849- let path_res = self . reborrow ( ) . maybe_resolve_path (
956+ let path_res = self . r . reborrow ( ) . maybe_resolve_path (
850957 & import. module_path ,
851958 None ,
852959 & import. parent_scope ,
@@ -855,8 +962,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
855962
856963 match path_res {
857964 PathResult :: Module ( module) => module,
858- PathResult :: Indeterminate => return 3 ,
859- PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => return 0 ,
965+ PathResult :: Indeterminate => return ( SideEffect :: None , 3 ) ,
966+ PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => {
967+ return ( SideEffect :: None , 0 ) ;
968+ }
860969 }
861970 } ;
862971
@@ -866,14 +975,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
866975 ( source, target, bindings, type_ns_only)
867976 }
868977 ImportKind :: Glob { .. } => {
869- self . get_mut_unchecked ( ) . resolve_glob_import ( import) ;
870- return 0 ;
978+ return ( self . resolve_glob_import ( import) , 0 ) ;
871979 }
872980 _ => unreachable ! ( ) ,
873981 } ;
874982
983+ let mut import_bindings = PerNS :: default ( ) ;
875984 let mut indeterminate_count = 0 ;
876- self . per_ns_cm ( |this, ns| {
985+ self . r . reborrow ( ) . per_ns_cm ( |this, ns| {
877986 if !type_ns_only || ns == TypeNS {
878987 if bindings[ ns] . get ( ) != PendingBinding :: Pending {
879988 return ;
@@ -885,8 +994,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
885994 & import. parent_scope ,
886995 Some ( import) ,
887996 ) ;
888- let parent = import. parent_scope . module ;
889- let binding = match binding_result {
997+ let pending_binding = match binding_result {
890998 Ok ( binding) => {
891999 if binding. is_assoc_item ( )
8921000 && !this. tcx . features ( ) . import_trait_associated_functions ( )
@@ -901,39 +1009,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9011009 }
9021010 // We need the `target`, `source` can be extracted.
9031011 let imported_binding = this. import ( binding, import) ;
904- this. get_mut_unchecked ( ) . define_binding_local (
905- parent,
906- target,
907- ns,
908- imported_binding,
909- ) ;
9101012 PendingBinding :: Ready ( Some ( imported_binding) )
9111013 }
9121014 Err ( Determinacy :: Determined ) => {
9131015 // Don't remove underscores from `single_imports`, they were never added.
914- if target. name != kw:: Underscore {
915- let key = BindingKey :: new ( target, ns) ;
916- this. get_mut_unchecked ( ) . update_local_resolution (
917- parent,
918- key,
919- false ,
920- |_, resolution| {
921- resolution. single_imports . swap_remove ( & import) ;
922- } ,
923- ) ;
1016+ if target. name == kw:: Underscore {
1017+ return ;
9241018 }
9251019 PendingBinding :: Ready ( None )
9261020 }
9271021 Err ( Determinacy :: Undetermined ) => {
9281022 indeterminate_count += 1 ;
929- PendingBinding :: Pending
1023+ return ;
9301024 }
9311025 } ;
9321026 bindings[ ns] . set_unchecked ( binding) ;
9331027 }
9341028 } ) ;
9351029
936- indeterminate_count
1030+ ( SideEffect :: Single { import_bindings } , indeterminate_count)
9371031 }
9381032
9391033 /// Performs final import resolution, consistency checks and error reporting.
@@ -1476,13 +1570,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14761570 false
14771571 }
14781572
1479- fn resolve_glob_import ( & mut self , import : Import < ' ra > ) {
1573+ fn resolve_glob_import < ' r > (
1574+ self : & mut ImportResolver < ' r , ' ra , ' tcx > ,
1575+ import : Import < ' ra > ,
1576+ ) -> SideEffect < ' ra > {
14801577 // This function is only called for glob imports.
1481- let ImportKind :: Glob { id , .. } = import. kind else { unreachable ! ( ) } ;
1578+ let ImportKind :: Glob { .. } = import. kind else { unreachable ! ( ) } ;
14821579
14831580 let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( ) else {
14841581 self . dcx ( ) . emit_err ( CannotGlobImportAllCrates { span : import. span } ) ;
1485- return ;
1582+ return SideEffect :: None ;
14861583 } ;
14871584
14881585 if module. is_trait ( ) && !self . tcx . features ( ) . import_trait_associated_functions ( ) {
@@ -1496,12 +1593,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14961593 }
14971594
14981595 if module == import. parent_scope . module {
1499- return ;
1596+ return SideEffect :: None ;
15001597 }
15011598
1502- // Add to module's glob_importers
1503- module. glob_importers . borrow_mut_unchecked ( ) . push ( import) ;
1504-
15051599 // Ensure that `resolutions` isn't borrowed during `try_define`,
15061600 // since it might get updated via a glob cycle.
15071601 let bindings = self
@@ -1512,6 +1606,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15121606 resolution. borrow ( ) . binding ( ) . map ( |binding| ( * key, binding) )
15131607 } )
15141608 . collect :: < Vec < _ > > ( ) ;
1609+ let mut import_bindings = Vec :: with_capacity ( bindings. len ( ) ) ;
15151610 for ( mut key, binding) in bindings {
15161611 let scope = match key. ident . 0 . span . reverse_glob_adjust ( module. expansion , import. span ) {
15171612 Some ( Some ( def) ) => self . expn_def_scope ( def) ,
@@ -1524,18 +1619,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15241619 . resolution ( import. parent_scope . module , key)
15251620 . and_then ( |r| r. binding ( ) )
15261621 . is_some_and ( |binding| binding. warn_ambiguity_recursive ( ) ) ;
1527- let _ = self . try_define_local (
1528- import. parent_scope . module ,
1529- key. ident . 0 ,
1530- key. ns ,
1531- imported_binding,
1532- warn_ambiguity,
1533- ) ;
1622+ import_bindings. push ( ( imported_binding, key, warn_ambiguity) ) ;
15341623 }
15351624 }
15361625
15371626 // Record the destination of this import
1538- self . record_partial_res ( id , PartialRes :: new ( module . res ( ) . unwrap ( ) ) ) ;
1627+ SideEffect :: Glob { import_bindings }
15391628 }
15401629
15411630 // Miscellaneous post-processing, including recording re-exports,
0 commit comments