1
1
//! A bunch of methods and structures more or less related to resolving imports.
2
2
3
3
use std:: mem;
4
+ use std:: ops:: Deref ;
4
5
5
6
use rustc_ast:: NodeId ;
6
7
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 ( 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
+
44
135
/// A [`NameBinding`] in the process of being resolved.
45
136
#[ derive( Clone , Copy , Default , PartialEq ) ]
46
137
pub ( crate ) enum PendingBinding < ' ra > {
@@ -553,22 +644,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
553
644
/// Resolves all imports for the crate. This method performs the fixed-
554
645
/// point iteration.
555
646
pub ( crate ) fn resolve_imports ( & mut self ) {
556
- self . assert_speculative = true ;
557
647
let mut prev_indeterminate_count = usize:: MAX ;
558
648
let mut indeterminate_count = self . indeterminate_imports . len ( ) * 3 ;
559
649
while indeterminate_count < prev_indeterminate_count {
560
650
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) ,
569
672
}
570
673
}
571
- self . assert_speculative = false ;
674
+ ( self . outputs , indeterminate_count )
572
675
}
573
676
574
677
pub ( crate ) fn finalize_imports ( & mut self ) {
@@ -837,7 +940,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
837
940
///
838
941
/// Meanwhile, if resolve successful, the resolved bindings are written
839
942
/// 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 ) {
841
947
debug ! (
842
948
"(resolving import for module) resolving import `{}::...` in `{}`" ,
843
949
Segment :: names_to_string( & import. module_path) ,
@@ -846,7 +952,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
846
952
let module = if let Some ( module) = import. imported_module . get ( ) {
847
953
module
848
954
} else {
849
- let path_res = self . reborrow ( ) . maybe_resolve_path (
955
+ let path_res = self . r . reborrow ( ) . maybe_resolve_path (
850
956
& import. module_path ,
851
957
None ,
852
958
& import. parent_scope ,
@@ -855,8 +961,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
855
961
856
962
match path_res {
857
963
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
+ }
860
968
}
861
969
} ;
862
970
@@ -867,16 +975,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
867
975
( source, target, bindings, type_ns_only)
868
976
}
869
977
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 ) ;
874
979
}
875
980
_ => unreachable ! ( ) ,
876
981
} ;
877
982
983
+ let mut import_bindings = PerNS :: default ( ) ;
878
984
let mut indeterminate_count = 0 ;
879
- self . per_ns_cm ( |this, ns| {
985
+ self . r . reborrow ( ) . per_ns_cm ( |this, ns| {
880
986
if !type_ns_only || ns == TypeNS {
881
987
if bindings[ ns] . get ( ) != PendingBinding :: Pending {
882
988
return ;
@@ -888,8 +994,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
888
994
& import. parent_scope ,
889
995
Some ( import) ,
890
996
) ;
891
- let parent = import. parent_scope . module ;
892
- let binding = match binding_result {
997
+ let pending_binding = match binding_result {
893
998
Ok ( binding) => {
894
999
if binding. is_assoc_item ( )
895
1000
&& !this. tcx . features ( ) . import_trait_associated_functions ( )
@@ -904,44 +1009,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
904
1009
}
905
1010
// We need the `target`, `source` can be extracted.
906
1011
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
- ) ;
915
1012
PendingBinding :: Ready ( Some ( imported_binding) )
916
1013
}
917
1014
Err ( Determinacy :: Determined ) => {
918
1015
// 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 ;
931
1018
}
932
1019
PendingBinding :: Ready ( None )
933
1020
}
934
1021
Err ( Determinacy :: Undetermined ) => {
935
1022
indeterminate_count += 1 ;
936
- PendingBinding :: Pending
1023
+ return ;
937
1024
}
938
1025
} ;
939
1026
// FIXME(batched): Will be fixed in batched import resolution.
940
1027
bindings[ ns] . set_unchecked ( 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_unchecked ( ) . 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