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,96 @@ use crate::{
41
42
42
43
type Res = def:: Res < NodeId > ;
43
44
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 ( ) . 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
+
44
135
/// A [`NameBinding`] in the process of being resolved.
45
136
#[ derive( Clone , Copy , Default , PartialEq ) ]
46
137
pub ( crate ) enum PendingBinding < ' ra > {
@@ -551,22 +642,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
551
642
/// Resolves all imports for the crate. This method performs the fixed-
552
643
/// point iteration.
553
644
pub ( crate ) fn resolve_imports ( & mut self ) {
554
- self . assert_speculative = true ;
555
645
let mut prev_indeterminate_count = usize:: MAX ;
556
646
let mut indeterminate_count = self . indeterminate_imports . len ( ) * 3 ;
557
647
while indeterminate_count < prev_indeterminate_count {
558
648
prev_indeterminate_count = indeterminate_count;
559
- indeterminate_count = 0 ;
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
- }
649
+ let batch = mem:: take ( & mut self . indeterminate_imports ) ;
650
+ self . assert_speculative = true ;
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) ,
567
670
}
568
671
}
569
- self . assert_speculative = false ;
672
+ ( self . outputs , indeterminate_count )
570
673
}
571
674
572
675
pub ( crate ) fn finalize_imports ( & mut self ) {
@@ -839,7 +942,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
839
942
///
840
943
/// Meanwhile, if resolve successful, the resolved bindings are written
841
944
/// into the module.
842
- fn resolve_import < ' r > ( mut self : CmResolver < ' r , ' ra , ' tcx > , import : Import < ' ra > ) -> usize {
945
+ fn resolve_import < ' r > (
946
+ self : & mut ImportResolver < ' r , ' ra , ' tcx > ,
947
+ import : Import < ' ra > ,
948
+ ) -> ( SideEffect < ' ra > , usize ) {
843
949
debug ! (
844
950
"(resolving import for module) resolving import `{}::...` in `{}`" ,
845
951
Segment :: names_to_string( & import. module_path) ,
@@ -848,7 +954,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
848
954
let module = if let Some ( module) = import. imported_module . get ( ) {
849
955
module
850
956
} else {
851
- let path_res = self . reborrow ( ) . maybe_resolve_path (
957
+ let path_res = self . r . reborrow ( ) . maybe_resolve_path (
852
958
& import. module_path ,
853
959
None ,
854
960
& import. parent_scope ,
@@ -857,8 +963,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
857
963
858
964
match path_res {
859
965
PathResult :: Module ( module) => module,
860
- PathResult :: Indeterminate => return 3 ,
861
- PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => return 0 ,
966
+ PathResult :: Indeterminate => return ( SideEffect :: None , 3 ) ,
967
+ PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => {
968
+ return ( SideEffect :: None , 0 ) ;
969
+ }
862
970
}
863
971
} ;
864
972
@@ -868,16 +976,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
868
976
( source, target, bindings, type_ns_only)
869
977
}
870
978
ImportKind :: Glob { .. } => {
871
- // FIXME: Use mutable resolver directly as a hack, this should be an output of
872
- // speculative resolution.
873
- self . get_mut_unchecked ( ) . resolve_glob_import ( import) ;
874
- return 0 ;
979
+ return ( self . resolve_glob_import ( import) , 0 ) ;
875
980
}
876
981
_ => unreachable ! ( ) ,
877
982
} ;
878
983
984
+ let mut import_bindings = PerNS :: default ( ) ;
879
985
let mut indeterminate_count = 0 ;
880
- self . per_ns_cm ( |this, ns| {
986
+ self . r . reborrow ( ) . per_ns_cm ( |this, ns| {
881
987
if !type_ns_only || ns == TypeNS {
882
988
if bindings[ ns] . get ( ) != PendingBinding :: Pending {
883
989
return ;
@@ -889,8 +995,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
889
995
& import. parent_scope ,
890
996
Some ( import) ,
891
997
) ;
892
- let parent = import. parent_scope . module ;
893
- let binding = match binding_result {
998
+ let pending_binding = match binding_result {
894
999
Ok ( binding) => {
895
1000
if binding. is_assoc_item ( )
896
1001
&& !this. tcx . features ( ) . import_trait_associated_functions ( )
@@ -905,43 +1010,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
905
1010
}
906
1011
// We need the `target`, `source` can be extracted.
907
1012
let imported_binding = this. import ( binding, import) ;
908
- // FIXME: Use mutable resolver directly as a hack, this should be an output of
909
- // speculative resolution.
910
- this. get_mut_unchecked ( ) . define_binding_local (
911
- parent,
912
- target,
913
- ns,
914
- imported_binding,
915
- ) ;
916
1013
PendingBinding :: Ready ( Some ( imported_binding) )
917
1014
}
918
1015
Err ( Determinacy :: Determined ) => {
919
1016
// Don't remove underscores from `single_imports`, they were never added.
920
- if target. name != kw:: Underscore {
921
- let key = BindingKey :: new ( target, ns) ;
922
- // FIXME: Use mutable resolver directly as a hack, this should be an output of
923
- // speculative resolution.
924
- this. get_mut_unchecked ( ) . update_local_resolution (
925
- parent,
926
- key,
927
- false ,
928
- |_, resolution| {
929
- resolution. single_imports . swap_remove ( & import) ;
930
- } ,
931
- ) ;
1017
+ if target. name == kw:: Underscore {
1018
+ return ;
932
1019
}
933
1020
PendingBinding :: Ready ( None )
934
1021
}
935
1022
Err ( Determinacy :: Undetermined ) => {
936
1023
indeterminate_count += 1 ;
937
- PendingBinding :: Pending
1024
+ return ;
938
1025
}
939
1026
} ;
940
- bindings [ ns] . set ( binding ) ;
1027
+ import_bindings [ ns] = pending_binding ;
941
1028
}
942
1029
} ) ;
943
1030
944
- indeterminate_count
1031
+ ( SideEffect :: Single { import_bindings } , indeterminate_count)
945
1032
}
946
1033
947
1034
/// Performs final import resolution, consistency checks and error reporting.
@@ -1484,13 +1571,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1484
1571
false
1485
1572
}
1486
1573
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 > {
1488
1578
// 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 ! ( ) } ;
1490
1580
1491
1581
let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( ) else {
1492
1582
self . dcx ( ) . emit_err ( CannotGlobImportAllCrates { span : import. span } ) ;
1493
- return ;
1583
+ return SideEffect :: None ;
1494
1584
} ;
1495
1585
1496
1586
if module. is_trait ( ) && !self . tcx . features ( ) . import_trait_associated_functions ( ) {
@@ -1504,12 +1594,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1504
1594
}
1505
1595
1506
1596
if module == import. parent_scope . module {
1507
- return ;
1597
+ return SideEffect :: None ;
1508
1598
}
1509
1599
1510
- // Add to module's glob_importers
1511
- module. glob_importers . borrow_mut ( ) . push ( import) ;
1512
-
1513
1600
// Ensure that `resolutions` isn't borrowed during `try_define`,
1514
1601
// since it might get updated via a glob cycle.
1515
1602
let bindings = self
@@ -1520,6 +1607,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1520
1607
resolution. borrow ( ) . binding ( ) . map ( |binding| ( * key, binding) )
1521
1608
} )
1522
1609
. collect :: < Vec < _ > > ( ) ;
1610
+ let mut import_bindings = Vec :: with_capacity ( bindings. len ( ) ) ;
1523
1611
for ( mut key, binding) in bindings {
1524
1612
let scope = match key. ident . 0 . span . reverse_glob_adjust ( module. expansion , import. span ) {
1525
1613
Some ( Some ( def) ) => self . expn_def_scope ( def) ,
@@ -1532,18 +1620,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1532
1620
. resolution ( import. parent_scope . module , key)
1533
1621
. and_then ( |r| r. binding ( ) )
1534
1622
. 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) ) ;
1542
1624
}
1543
1625
}
1544
1626
1545
1627
// Record the destination of this import
1546
- self . record_partial_res ( id , PartialRes :: new ( module . res ( ) . unwrap ( ) ) ) ;
1628
+ SideEffect :: Glob { import_bindings }
1547
1629
}
1548
1630
1549
1631
// Miscellaneous post-processing, including recording re-exports,
0 commit comments