22
33use std:: cell:: Cell ;
44use std:: mem;
5+ use std:: ops:: Deref ;
56
67use rustc_ast:: NodeId ;
78use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
@@ -41,6 +42,53 @@ use crate::{
4142
4243type Res = def:: Res < NodeId > ;
4344
45+ pub ( crate ) struct ImportResolver < ' r , ' ra , ' tcx > {
46+ r : CmResolver < ' r , ' ra , ' tcx > , // always immutable
47+ batch : Vec < Import < ' ra > > , // a.k.a. indeterminate_imports, also treated as output
48+
49+ // outputs
50+ determined_imports : Vec < Import < ' ra > > ,
51+ }
52+
53+ struct ImportResolutionOutputs < ' ra > {
54+ indeterminate_imports : Vec < Import < ' ra > > ,
55+ determined_imports : Vec < Import < ' ra > > ,
56+ }
57+
58+ impl < ' r , ' ra , ' tcx > ImportResolver < ' r , ' ra , ' tcx > {
59+ pub ( crate ) fn new ( cmr : CmResolver < ' r , ' ra , ' tcx > , batch : Vec < Import < ' ra > > ) -> Self {
60+ ImportResolver { r : cmr, batch, determined_imports : Vec :: new ( ) }
61+ }
62+
63+ fn into_outputs ( self ) -> ImportResolutionOutputs < ' ra > {
64+ ImportResolutionOutputs {
65+ indeterminate_imports : self . batch ,
66+ determined_imports : self . determined_imports ,
67+ }
68+ }
69+ }
70+
71+ impl < ' ra > ImportResolutionOutputs < ' ra > {
72+ fn commit < ' tcx > ( self , r : & mut Resolver < ' ra , ' tcx > ) {
73+ r. indeterminate_imports = self . indeterminate_imports ;
74+ r. determined_imports . extend ( self . determined_imports ) ;
75+ }
76+ }
77+
78+ impl < ' r , ' ra , ' tcx > Deref for ImportResolver < ' r , ' ra , ' tcx > {
79+ type Target = Resolver < ' ra , ' tcx > ;
80+
81+ fn deref ( & self ) -> & Self :: Target {
82+ self . r . deref ( )
83+ }
84+ }
85+
86+ impl < ' r , ' ra , ' tcx > AsRef < Resolver < ' ra , ' tcx > > for ImportResolver < ' r , ' ra , ' tcx > {
87+ fn as_ref ( & self ) -> & Resolver < ' ra , ' tcx > {
88+ self . r . as_ref ( )
89+ }
90+ }
91+
4492/// A [`NameBinding`] in the process of being resolved.
4593#[ derive( Clone , Copy , Default , PartialEq ) ]
4694pub ( crate ) enum PendingBinding < ' ra > {
@@ -552,22 +600,32 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
552600 /// Resolves all imports for the crate. This method performs the fixed-
553601 /// point iteration.
554602 pub ( crate ) fn resolve_imports ( & mut self ) {
555- self . assert_speculative = true ;
556603 let mut prev_indeterminate_count = usize:: MAX ;
557604 let mut indeterminate_count = self . indeterminate_imports . len ( ) * 3 ;
558605 while indeterminate_count < prev_indeterminate_count {
606+ self . assert_speculative = true ;
559607 prev_indeterminate_count = indeterminate_count;
560- indeterminate_count = 0 ;
561- for import in mem:: take ( & mut self . indeterminate_imports ) {
562- let import_indeterminate_count = self . cm ( ) . resolve_import ( import) ;
563- indeterminate_count += import_indeterminate_count;
564- match import_indeterminate_count {
565- 0 => self . determined_imports . push ( import) ,
566- _ => self . indeterminate_imports . push ( import) ,
567- }
608+ let batch = mem:: take ( & mut self . indeterminate_imports ) ;
609+ let ( outputs, count) = ImportResolver :: new ( self . cm ( ) , batch) . resolve_batch ( ) ;
610+ indeterminate_count = count;
611+ self . assert_speculative = false ;
612+ outputs. commit ( self ) ;
613+ }
614+ }
615+
616+ fn resolve_batch < ' r > (
617+ mut self : ImportResolver < ' r , ' ra , ' tcx > ,
618+ ) -> ( ImportResolutionOutputs < ' ra > , usize ) {
619+ let mut indeterminate_count = 0 ;
620+ for import in mem:: take ( & mut self . batch ) {
621+ let import_indeterminate_count = self . resolve_import ( import) ;
622+ indeterminate_count += import_indeterminate_count;
623+ match import_indeterminate_count {
624+ 0 => self . determined_imports . push ( import) ,
625+ _ => self . batch . push ( import) ,
568626 }
569627 }
570- self . assert_speculative = false ;
628+ ( self . into_outputs ( ) , indeterminate_count )
571629 }
572630
573631 pub ( crate ) fn finalize_imports ( & mut self ) {
@@ -840,7 +898,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
840898 ///
841899 /// Meanwhile, if resolve successful, the resolved bindings are written
842900 /// into the module.
843- fn resolve_import < ' r > ( mut self : CmResolver < ' r , ' ra , ' tcx > , import : Import < ' ra > ) -> usize {
901+ fn resolve_import < ' r > ( self : & mut ImportResolver < ' r , ' ra , ' tcx > , import : Import < ' ra > ) -> usize {
844902 debug ! (
845903 "(resolving import for module) resolving import `{}::...` in `{}`" ,
846904 Segment :: names_to_string( & import. module_path) ,
@@ -849,7 +907,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
849907 let module = if let Some ( module) = import. imported_module . get ( ) {
850908 module
851909 } else {
852- let path_res = self . reborrow ( ) . maybe_resolve_path (
910+ let path_res = self . r . reborrow ( ) . maybe_resolve_path (
853911 & import. module_path ,
854912 None ,
855913 & import. parent_scope ,
@@ -871,14 +929,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
871929 ImportKind :: Glob { .. } => {
872930 // FIXME: Use mutable resolver directly as a hack, this should be an output of
873931 // specualtive resolution.
874- self . get_mut_unchecked ( ) . resolve_glob_import ( import) ;
932+ self . r . get_mut_unchecked ( ) . resolve_glob_import ( import) ;
875933 return 0 ;
876934 }
877935 _ => unreachable ! ( ) ,
878936 } ;
879937
880938 let mut indeterminate_count = 0 ;
881- self . per_ns_cm ( |this, ns| {
939+ self . r . reborrow ( ) . per_ns_cm ( |this, ns| {
882940 if !type_ns_only || ns == TypeNS {
883941 if bindings[ ns] . get ( ) != PendingBinding :: Pending {
884942 return ;
0 commit comments