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 > {
@@ -553,22 +644,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
553644 /// Resolves all imports for the crate. This method performs the fixed-
554645 /// point iteration.
555646 pub ( crate ) fn resolve_imports ( & mut self ) {
556- self . assert_speculative = true ;
557647 let mut prev_indeterminate_count = usize:: MAX ;
558648 let mut indeterminate_count = self . indeterminate_imports . len ( ) * 3 ;
559649 while indeterminate_count < prev_indeterminate_count {
560650 prev_indeterminate_count = indeterminate_count;
561- indeterminate_count = 0 ;
562- for import in mem:: take ( & mut self . indeterminate_imports ) {
563- let import_indeterminate_count = self . cm ( ) . resolve_import ( import) ;
564- indeterminate_count += import_indeterminate_count;
565- match import_indeterminate_count {
566- 0 => self . determined_imports . push ( import) ,
567- _ => self . indeterminate_imports . push ( import) ,
568- }
651+ let batch = mem:: take ( & mut self . indeterminate_imports ) ;
652+ self . assert_speculative = true ;
653+ let ( outputs, count) =
654+ ImportResolver { r : self . cm ( ) , outputs : Default :: default ( ) } . resolve_batch ( batch) ;
655+ self . assert_speculative = false ;
656+ indeterminate_count = count;
657+ outputs. commit ( self ) ;
658+ }
659+ }
660+
661+ fn resolve_batch < ' r > (
662+ mut self : ImportResolver < ' r , ' ra , ' tcx > ,
663+ batch : Vec < Import < ' ra > > ,
664+ ) -> ( ImportResolutionOutputs < ' ra > , usize ) {
665+ let mut indeterminate_count = 0 ;
666+ for import in batch {
667+ let ( side_effect, import_indeterminate_count) = self . resolve_import ( import) ;
668+ indeterminate_count += import_indeterminate_count;
669+ match import_indeterminate_count {
670+ 0 => self . outputs . determined_imports . push ( ( import, side_effect) ) ,
671+ _ => self . outputs . indeterminate_imports . push ( import) ,
569672 }
570673 }
571- self . assert_speculative = false ;
674+ ( self . outputs , indeterminate_count )
572675 }
573676
574677 pub ( crate ) fn finalize_imports ( & mut self ) {
@@ -837,7 +940,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
837940 ///
838941 /// Meanwhile, if resolve successful, the resolved bindings are written
839942 /// into the module.
840- fn resolve_import < ' r > ( mut self : CmResolver < ' r , ' ra , ' tcx > , import : Import < ' ra > ) -> usize {
943+ fn resolve_import < ' r > (
944+ self : & mut ImportResolver < ' r , ' ra , ' tcx > ,
945+ import : Import < ' ra > ,
946+ ) -> ( SideEffect < ' ra > , usize ) {
841947 debug ! (
842948 "(resolving import for module) resolving import `{}::...` in `{}`" ,
843949 Segment :: names_to_string( & import. module_path) ,
@@ -846,7 +952,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
846952 let module = if let Some ( module) = import. imported_module . get ( ) {
847953 module
848954 } else {
849- let path_res = self . reborrow ( ) . maybe_resolve_path (
955+ let path_res = self . r . reborrow ( ) . maybe_resolve_path (
850956 & import. module_path ,
851957 None ,
852958 & import. parent_scope ,
@@ -855,8 +961,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
855961
856962 match path_res {
857963 PathResult :: Module ( module) => module,
858- PathResult :: Indeterminate => return 3 ,
859- PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => return 0 ,
964+ PathResult :: Indeterminate => return ( SideEffect :: None , 3 ) ,
965+ PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => {
966+ return ( SideEffect :: None , 0 ) ;
967+ }
860968 }
861969 } ;
862970
@@ -867,16 +975,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
867975 ( source, target, bindings, type_ns_only)
868976 }
869977 ImportKind :: Glob { .. } => {
870- // FIXME: Use mutable resolver directly as a hack, this should be an output of
871- // speculative resolution.
872- self . get_mut_unchecked ( ) . resolve_glob_import ( import) ;
873- return 0 ;
978+ return ( self . resolve_glob_import ( import) , 0 ) ;
874979 }
875980 _ => unreachable ! ( ) ,
876981 } ;
877982
983+ let mut import_bindings = PerNS :: default ( ) ;
878984 let mut indeterminate_count = 0 ;
879- self . per_ns_cm ( |this, ns| {
985+ self . r . reborrow ( ) . per_ns_cm ( |this, ns| {
880986 if !type_ns_only || ns == TypeNS {
881987 if bindings[ ns] . get ( ) != PendingBinding :: Pending {
882988 return ;
@@ -888,8 +994,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
888994 & import. parent_scope ,
889995 Some ( import) ,
890996 ) ;
891- let parent = import. parent_scope . module ;
892- let binding = match binding_result {
997+ let pending_binding = match binding_result {
893998 Ok ( binding) => {
894999 if binding. is_assoc_item ( )
8951000 && !this. tcx . features ( ) . import_trait_associated_functions ( )
@@ -904,44 +1009,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9041009 }
9051010 // We need the `target`, `source` can be extracted.
9061011 let imported_binding = this. import ( binding, import) ;
907- // FIXME: Use mutable resolver directly as a hack, this should be an output of
908- // speculative resolution.
909- this. get_mut_unchecked ( ) . define_binding_local (
910- parent,
911- target,
912- ns,
913- imported_binding,
914- ) ;
9151012 PendingBinding :: Ready ( Some ( imported_binding) )
9161013 }
9171014 Err ( Determinacy :: Determined ) => {
9181015 // Don't remove underscores from `single_imports`, they were never added.
919- if target. name != kw:: Underscore {
920- let key = BindingKey :: new ( target, ns) ;
921- // FIXME: Use mutable resolver directly as a hack, this should be an output of
922- // speculative resolution.
923- this. get_mut_unchecked ( ) . update_local_resolution (
924- parent,
925- key,
926- false ,
927- |_, resolution| {
928- resolution. single_imports . swap_remove ( & import) ;
929- } ,
930- ) ;
1016+ if target. name == kw:: Underscore {
1017+ return ;
9311018 }
9321019 PendingBinding :: Ready ( None )
9331020 }
9341021 Err ( Determinacy :: Undetermined ) => {
9351022 indeterminate_count += 1 ;
936- PendingBinding :: Pending
1023+ return ;
9371024 }
9381025 } ;
9391026 // FIXME(batched): Will be fixed in batched import resolution.
9401027 bindings[ ns] . set_unchecked ( binding) ;
9411028 }
9421029 } ) ;
9431030
944- indeterminate_count
1031+ ( SideEffect :: Single { import_bindings } , indeterminate_count)
9451032 }
9461033
9471034 /// Performs final import resolution, consistency checks and error reporting.
@@ -1484,13 +1571,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14841571 false
14851572 }
14861573
1487- fn resolve_glob_import ( & mut self , import : Import < ' ra > ) {
1574+ fn resolve_glob_import < ' r > (
1575+ self : & mut ImportResolver < ' r , ' ra , ' tcx > ,
1576+ import : Import < ' ra > ,
1577+ ) -> SideEffect < ' ra > {
14881578 // This function is only called for glob imports.
1489- let ImportKind :: Glob { id , .. } = import. kind else { unreachable ! ( ) } ;
1579+ let ImportKind :: Glob { .. } = import. kind else { unreachable ! ( ) } ;
14901580
14911581 let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( ) else {
14921582 self . dcx ( ) . emit_err ( CannotGlobImportAllCrates { span : import. span } ) ;
1493- return ;
1583+ return SideEffect :: None ;
14941584 } ;
14951585
14961586 if module. is_trait ( ) && !self . tcx . features ( ) . import_trait_associated_functions ( ) {
@@ -1504,12 +1594,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15041594 }
15051595
15061596 if module == import. parent_scope . module {
1507- return ;
1597+ return SideEffect :: None ;
15081598 }
15091599
1510- // Add to module's glob_importers
1511- module. glob_importers . borrow_mut_unchecked ( ) . push ( import) ;
1512-
15131600 // Ensure that `resolutions` isn't borrowed during `try_define`,
15141601 // since it might get updated via a glob cycle.
15151602 let bindings = self
@@ -1520,6 +1607,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15201607 resolution. borrow ( ) . binding ( ) . map ( |binding| ( * key, binding) )
15211608 } )
15221609 . collect :: < Vec < _ > > ( ) ;
1610+ let mut import_bindings = Vec :: with_capacity ( bindings. len ( ) ) ;
15231611 for ( mut key, binding) in bindings {
15241612 let scope = match key. ident . 0 . span . reverse_glob_adjust ( module. expansion , import. span ) {
15251613 Some ( Some ( def) ) => self . expn_def_scope ( def) ,
@@ -1532,18 +1620,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15321620 . resolution ( import. parent_scope . module , key)
15331621 . and_then ( |r| r. binding ( ) )
15341622 . is_some_and ( |binding| binding. warn_ambiguity_recursive ( ) ) ;
1535- let _ = self . try_define_local (
1536- import. parent_scope . module ,
1537- key. ident . 0 ,
1538- key. ns ,
1539- imported_binding,
1540- warn_ambiguity,
1541- ) ;
1623+ import_bindings. push ( ( imported_binding, key, warn_ambiguity) ) ;
15421624 }
15431625 }
15441626
15451627 // Record the destination of this import
1546- self . record_partial_res ( id , PartialRes :: new ( module . res ( ) . unwrap ( ) ) ) ;
1628+ SideEffect :: Glob { import_bindings }
15471629 }
15481630
15491631 // Miscellaneous post-processing, including recording re-exports,
0 commit comments