@@ -5,7 +5,7 @@ use std::mem;
5
5
use std:: ops:: Deref ;
6
6
7
7
use rustc_ast:: NodeId ;
8
- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
8
+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
9
9
use rustc_data_structures:: intern:: Interned ;
10
10
use rustc_errors:: codes:: * ;
11
11
use rustc_errors:: { Applicability , MultiSpan , pluralize, struct_span_code_err} ;
@@ -47,59 +47,89 @@ struct ImportResolver<'r, 'ra, 'tcx> {
47
47
outputs : ImportResolutionOutputs < ' ra > ,
48
48
}
49
49
50
+ enum SideEffect < ' ra > {
51
+ None ,
52
+ Prelude ,
53
+ Single {
54
+ parent : Module < ' ra > ,
55
+ import_bindings : PerNS < PendingBinding < ' ra > > ,
56
+ } ,
57
+ Glob {
58
+ parent : Module < ' ra > ,
59
+ import_bindings : Vec < ( NameBinding < ' ra > , BindingKey , bool /* warn_ambiguity */ ) > ,
60
+ path_res : PartialRes ,
61
+ } ,
62
+ }
63
+
50
64
#[ derive( Default ) ]
51
65
struct ImportResolutionOutputs < ' ra > {
52
- prelude : Option < Module < ' ra > > ,
53
66
indeterminate_imports : Vec < Import < ' ra > > ,
54
- determined_imports : Vec < Import < ' ra > > ,
55
- module_glob_importers : FxIndexMap < Module < ' ra > , Vec < Import < ' ra > > > ,
56
- glob_import_bindings :
57
- Vec < ( Module < ' ra > , BindingKey , NameBinding < ' ra > , bool /* warn_ambiguity */ ) > ,
58
- glob_path_res : Vec < ( NodeId , PartialRes ) > ,
59
- single_import_bindings : PerNS < Vec < ( Module < ' ra > , Import < ' ra > , PendingBinding < ' ra > ) > > ,
67
+ determined_imports : Vec < ( Import < ' ra > , SideEffect < ' ra > ) > ,
60
68
}
61
69
62
70
impl < ' ra > ImportResolutionOutputs < ' ra > {
63
71
fn commit < ' tcx > ( self , r : & mut Resolver < ' ra , ' tcx > ) {
64
72
r. indeterminate_imports = self . indeterminate_imports ;
65
- r. determined_imports . extend ( self . determined_imports ) ;
66
-
67
- // It's possible this particular round didn't set the prelude, so we should not
68
- // unset it in the main resolver.
69
- if self . prelude . is_some ( ) {
70
- r. prelude = self . prelude ;
71
- }
72
-
73
- for ( module, glob_importers) in self . module_glob_importers {
74
- module. glob_importers . borrow_mut ( ) . extend ( glob_importers) ;
75
- }
76
-
77
- for ( module, key, binding, warn_ambiguity) in self . glob_import_bindings {
78
- let _ = r. try_define_local ( module, key. ident . 0 , key. ns , binding, warn_ambiguity) ;
79
- }
73
+ r. determined_imports . reserve ( self . determined_imports . len ( ) ) ;
74
+
75
+ for ( import, side_effect) in self . determined_imports {
76
+ r. determined_imports . push ( import) ;
77
+
78
+ match ( & import. kind , side_effect) {
79
+ (
80
+ ImportKind :: Single { target, bindings, .. } ,
81
+ SideEffect :: Single { parent, import_bindings } ,
82
+ ) => {
83
+ for ( ns, pending_binding) in import_bindings. into_iter_with ( ) {
84
+ match pending_binding {
85
+ PendingBinding :: Ready ( Some ( binding) ) => {
86
+ r. define_binding_local ( parent, * target, ns, binding) ;
87
+ }
88
+ PendingBinding :: Ready ( None ) => {
89
+ let key = BindingKey :: new ( * target, ns) ;
90
+ r. update_local_resolution ( parent, key, false , |_, resolution| {
91
+ resolution. single_imports . swap_remove ( & import) ;
92
+ } ) ;
93
+ }
94
+ _ => { }
95
+ }
96
+ bindings[ ns] . set ( pending_binding) ;
97
+ }
98
+ }
99
+ (
100
+ ImportKind :: Glob { id, .. } ,
101
+ SideEffect :: Glob { parent, import_bindings, path_res } ,
102
+ ) => {
103
+ let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( )
104
+ else {
105
+ unreachable ! ( ) ;
106
+ } ;
80
107
81
- for ( id, res) in self . glob_path_res {
82
- r. record_partial_res ( id, res) ;
83
- }
108
+ module. glob_importers . borrow_mut ( ) . push ( import) ;
84
109
85
- for ( ns, import_bindings) in self . single_import_bindings . into_iter_with ( ) {
86
- for ( parent, import, pending_binding) in import_bindings {
87
- let ImportKind :: Single { target, ref bindings, .. } = import. kind else {
88
- unreachable ! ( ) ;
89
- } ;
90
- match pending_binding {
91
- PendingBinding :: Ready ( Some ( binding) ) => {
92
- r. define_binding_local ( parent, target, ns, binding) ;
93
- }
94
- PendingBinding :: Ready ( None ) => {
95
- let key = BindingKey :: new ( target, ns) ;
96
- r. update_local_resolution ( parent, key, false , |_, resolution| {
97
- resolution. single_imports . swap_remove ( & import) ;
98
- } ) ;
110
+ for ( binding, key, warn_ambiguity) in import_bindings {
111
+ let _ = r. try_define_local (
112
+ parent,
113
+ key. ident . 0 ,
114
+ key. ns ,
115
+ binding,
116
+ warn_ambiguity,
117
+ ) ;
99
118
}
100
- _ => { }
119
+
120
+ r. record_partial_res ( * id, path_res) ;
101
121
}
102
- bindings[ ns] . set ( pending_binding) ;
122
+ ( ImportKind :: Glob { is_prelude : true , .. } , SideEffect :: Prelude ) => {
123
+ let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( )
124
+ else {
125
+ unreachable ! ( )
126
+ } ;
127
+ r. prelude = Some ( module) ;
128
+ }
129
+
130
+ ( _, SideEffect :: None ) => { }
131
+ // Something weird happened, which shouldn't have happened.
132
+ _ => unreachable ! ( "Mismatched import kind and side effect" ) ,
103
133
}
104
134
}
105
135
}
@@ -650,10 +680,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
650
680
) -> ( ImportResolutionOutputs < ' ra > , usize ) {
651
681
let mut indeterminate_count = 0 ;
652
682
for import in batch {
653
- let import_indeterminate_count = self . resolve_import ( import) ;
683
+ let ( side_effect , import_indeterminate_count) = self . resolve_import ( import) ;
654
684
indeterminate_count += import_indeterminate_count;
655
685
match import_indeterminate_count {
656
- 0 => self . outputs . determined_imports . push ( import) ,
686
+ 0 => self . outputs . determined_imports . push ( ( import, side_effect ) ) ,
657
687
_ => self . outputs . indeterminate_imports . push ( import) ,
658
688
}
659
689
}
@@ -930,7 +960,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
930
960
///
931
961
/// Meanwhile, if resolve successful, the resolved bindings are written
932
962
/// into the module.
933
- fn resolve_import < ' r > ( self : & mut ImportResolver < ' r , ' ra , ' tcx > , import : Import < ' ra > ) -> usize {
963
+ fn resolve_import < ' r > (
964
+ self : & mut ImportResolver < ' r , ' ra , ' tcx > ,
965
+ import : Import < ' ra > ,
966
+ ) -> ( SideEffect < ' ra > , usize ) {
934
967
debug ! (
935
968
"(resolving import for module) resolving import `{}::{}` in `{}`" ,
936
969
Segment :: names_to_string( & import. module_path) ,
@@ -949,8 +982,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
949
982
950
983
match path_res {
951
984
PathResult :: Module ( module) => module,
952
- PathResult :: Indeterminate => return 3 ,
953
- PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => return 0 ,
985
+ PathResult :: Indeterminate => return ( SideEffect :: None , 3 ) ,
986
+ PathResult :: NonModule ( ..) | PathResult :: Failed { .. } => {
987
+ return ( SideEffect :: None , 0 ) ;
988
+ }
954
989
}
955
990
} ;
956
991
@@ -960,12 +995,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
960
995
( source, target, bindings, type_ns_only)
961
996
}
962
997
ImportKind :: Glob { .. } => {
963
- self . resolve_glob_import ( import) ;
964
- return 0 ;
998
+ return ( self . resolve_glob_import ( import) , 0 ) ;
965
999
}
966
1000
_ => unreachable ! ( ) ,
967
1001
} ;
968
1002
1003
+ let mut import_bindings = PerNS :: default ( ) ;
969
1004
let mut indeterminate_count = 0 ;
970
1005
self . r . reborrow ( ) . per_ns_cm ( |this, ns| {
971
1006
if !type_ns_only || ns == TypeNS {
@@ -979,7 +1014,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
979
1014
& import. parent_scope ,
980
1015
Some ( import) ,
981
1016
) ;
982
- let parent = import. parent_scope . module ;
983
1017
let pending_binding = match binding_result {
984
1018
Ok ( binding) => {
985
1019
if binding. is_assoc_item ( )
@@ -1009,11 +1043,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1009
1043
return ;
1010
1044
}
1011
1045
} ;
1012
- self . outputs . single_import_bindings [ ns] . push ( ( parent , import , pending_binding) ) ;
1046
+ import_bindings [ ns] = pending_binding;
1013
1047
}
1014
1048
} ) ;
1015
1049
1016
- indeterminate_count
1050
+ (
1051
+ SideEffect :: Single { parent : import. parent_scope . module , import_bindings } ,
1052
+ indeterminate_count,
1053
+ )
1017
1054
}
1018
1055
1019
1056
/// Performs final import resolution, consistency checks and error reporting.
@@ -1554,13 +1591,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1554
1591
false
1555
1592
}
1556
1593
1557
- fn resolve_glob_import < ' r > ( self : & mut ImportResolver < ' r , ' ra , ' tcx > , import : Import < ' ra > ) {
1594
+ fn resolve_glob_import < ' r > (
1595
+ self : & mut ImportResolver < ' r , ' ra , ' tcx > ,
1596
+ import : Import < ' ra > ,
1597
+ ) -> SideEffect < ' ra > {
1558
1598
// This function is only called for glob imports.
1559
- let ImportKind :: Glob { id , is_prelude, .. } = import. kind else { unreachable ! ( ) } ;
1599
+ let ImportKind :: Glob { is_prelude, .. } = import. kind else { unreachable ! ( ) } ;
1560
1600
1561
1601
let ModuleOrUniformRoot :: Module ( module) = import. imported_module . get ( ) . unwrap ( ) else {
1562
1602
self . dcx ( ) . emit_err ( CannotGlobImportAllCrates { span : import. span } ) ;
1563
- return ;
1603
+ return SideEffect :: None ;
1564
1604
} ;
1565
1605
1566
1606
if module. is_trait ( ) && !self . tcx . features ( ) . import_trait_associated_functions ( ) {
@@ -1574,15 +1614,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1574
1614
}
1575
1615
1576
1616
if module == import. parent_scope . module {
1577
- return ;
1617
+ return SideEffect :: None ;
1578
1618
} else if is_prelude {
1579
- self . outputs . prelude = Some ( module) ;
1580
- return ;
1619
+ return SideEffect :: Prelude ;
1581
1620
}
1582
1621
1583
- // Add to module's glob_importers
1584
- self . outputs . module_glob_importers . entry ( module) . or_default ( ) . push ( import) ;
1585
-
1586
1622
// Ensure that `resolutions` isn't borrowed during `try_define`,
1587
1623
// since it might get updated via a glob cycle.
1588
1624
let bindings = self
@@ -1593,6 +1629,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1593
1629
resolution. borrow ( ) . binding ( ) . map ( |binding| ( * key, binding) )
1594
1630
} )
1595
1631
. collect :: < Vec < _ > > ( ) ;
1632
+ let mut import_bindings = Vec :: with_capacity ( bindings. len ( ) ) ;
1596
1633
for ( mut key, binding) in bindings {
1597
1634
let scope = match key. ident . 0 . span . reverse_glob_adjust ( module. expansion , import. span ) {
1598
1635
Some ( Some ( def) ) => self . expn_def_scope ( def) ,
@@ -1605,17 +1642,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1605
1642
. resolution ( import. parent_scope . module , key)
1606
1643
. and_then ( |r| r. binding ( ) )
1607
1644
. is_some_and ( |binding| binding. warn_ambiguity_recursive ( ) ) ;
1608
- self . outputs . glob_import_bindings . push ( (
1609
- import. parent_scope . module ,
1610
- key,
1611
- imported_binding,
1612
- warn_ambiguity,
1613
- ) ) ;
1645
+ import_bindings. push ( ( imported_binding, key, warn_ambiguity) ) ;
1614
1646
}
1615
1647
}
1616
1648
1617
1649
// Record the destination of this import
1618
- self . outputs . glob_path_res . push ( ( id, PartialRes :: new ( module. res ( ) . unwrap ( ) ) ) ) ;
1650
+ SideEffect :: Glob {
1651
+ parent : import. parent_scope . module ,
1652
+ import_bindings,
1653
+ path_res : PartialRes :: new ( module. res ( ) . unwrap ( ) ) ,
1654
+ }
1619
1655
}
1620
1656
1621
1657
// Miscellaneous post-processing, including recording re-exports,
0 commit comments