2
2
3
3
use std:: cell:: Cell ;
4
4
use std:: mem;
5
+ use std:: ops:: Deref ;
5
6
6
7
use rustc_ast:: NodeId ;
7
8
use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
@@ -41,6 +42,53 @@ use crate::{
41
42
42
43
type Res = def:: Res < NodeId > ;
43
44
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
+
44
92
/// A [`NameBinding`] in the process of being resolved.
45
93
#[ derive( Clone , Copy , Default , PartialEq ) ]
46
94
pub ( crate ) enum PendingBinding < ' ra > {
@@ -552,22 +600,32 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
552
600
/// Resolves all imports for the crate. This method performs the fixed-
553
601
/// point iteration.
554
602
pub ( crate ) fn resolve_imports ( & mut self ) {
555
- self . assert_speculative = true ;
556
603
let mut prev_indeterminate_count = usize:: MAX ;
557
604
let mut indeterminate_count = self . indeterminate_imports . len ( ) * 3 ;
558
605
while indeterminate_count < prev_indeterminate_count {
606
+ self . assert_speculative = true ;
559
607
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) ,
568
626
}
569
627
}
570
- self . assert_speculative = false ;
628
+ ( self . into_outputs ( ) , indeterminate_count )
571
629
}
572
630
573
631
pub ( crate ) fn finalize_imports ( & mut self ) {
@@ -840,7 +898,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
840
898
///
841
899
/// Meanwhile, if resolve successful, the resolved bindings are written
842
900
/// 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 {
844
902
debug ! (
845
903
"(resolving import for module) resolving import `{}::...` in `{}`" ,
846
904
Segment :: names_to_string( & import. module_path) ,
@@ -849,7 +907,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
849
907
let module = if let Some ( module) = import. imported_module . get ( ) {
850
908
module
851
909
} else {
852
- let path_res = self . reborrow ( ) . maybe_resolve_path (
910
+ let path_res = self . r . reborrow ( ) . maybe_resolve_path (
853
911
& import. module_path ,
854
912
None ,
855
913
& import. parent_scope ,
@@ -871,14 +929,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
871
929
ImportKind :: Glob { .. } => {
872
930
// FIXME: Use mutable resolver directly as a hack, this should be an output of
873
931
// specualtive resolution.
874
- self . get_mut_unchecked ( ) . resolve_glob_import ( import) ;
932
+ self . r . get_mut_unchecked ( ) . resolve_glob_import ( import) ;
875
933
return 0 ;
876
934
}
877
935
_ => unreachable ! ( ) ,
878
936
} ;
879
937
880
938
let mut indeterminate_count = 0 ;
881
- self . per_ns_cm ( |this, ns| {
939
+ self . r . reborrow ( ) . per_ns_cm ( |this, ns| {
882
940
if !type_ns_only || ns == TypeNS {
883
941
if bindings[ ns] . get ( ) != PendingBinding :: Pending {
884
942
return ;
0 commit comments