@@ -7,7 +7,7 @@ use super::FnCtxt;
7
7
use rustc:: hir:: map:: Map ;
8
8
use rustc:: middle:: region:: { self , YieldData } ;
9
9
use rustc:: ty:: { self , Ty } ;
10
- use rustc_data_structures:: fx:: FxHashMap ;
10
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
11
11
use rustc_hir as hir;
12
12
use rustc_hir:: def:: { CtorKind , DefKind , Res } ;
13
13
use rustc_hir:: def_id:: DefId ;
@@ -160,33 +160,39 @@ pub fn resolve_interior<'a, 'tcx>(
160
160
161
161
debug ! ( "types in generator {:?}, span = {:?}" , types, body. value. span) ;
162
162
163
- // Replace all regions inside the generator interior with late bound regions
164
- // Note that each region slot in the types gets a new fresh late bound region,
165
- // which means that none of the regions inside relate to any other, even if
166
- // typeck had previously found constraints that would cause them to be related.
167
163
let mut counter = 0 ;
168
- let fold_types: Vec < _ > = types. iter ( ) . map ( |( t, _) | t. ty ) . collect ( ) ;
169
- let folded_types = fcx. tcx . fold_regions ( & fold_types, & mut false , |_, current_depth| {
170
- counter += 1 ;
171
- fcx. tcx . mk_region ( ty:: ReLateBound ( current_depth, ty:: BrAnon ( counter) ) )
172
- } ) ;
173
-
174
- // Store the generator types and spans into the tables for this generator.
175
- let types = types
164
+ let mut captured_tys = FxHashSet :: default ( ) ;
165
+ let type_causes: Vec < _ > = types
176
166
. into_iter ( )
177
- . zip ( & folded_types)
178
- . map ( |( ( mut interior_cause, _) , ty) | {
179
- interior_cause. ty = ty;
180
- interior_cause
167
+ . filter_map ( |( mut cause, _) | {
168
+ // Erase regions and canonicalize late-bound regions to deduplicate as many types as we
169
+ // can.
170
+ let erased = fcx. tcx . erase_regions ( & cause. ty ) ;
171
+ if captured_tys. insert ( erased) {
172
+ // Replace all regions inside the generator interior with late bound regions.
173
+ // Note that each region slot in the types gets a new fresh late bound region,
174
+ // which means that none of the regions inside relate to any other, even if
175
+ // typeck had previously found constraints that would cause them to be related.
176
+ let folded = fcx. tcx . fold_regions ( & erased, & mut false , |_, current_depth| {
177
+ counter += 1 ;
178
+ fcx. tcx . mk_region ( ty:: ReLateBound ( current_depth, ty:: BrAnon ( counter) ) )
179
+ } ) ;
180
+
181
+ cause. ty = folded;
182
+ Some ( cause)
183
+ } else {
184
+ None
185
+ }
181
186
} )
182
187
. collect ( ) ;
183
- visitor. fcx . inh . tables . borrow_mut ( ) . generator_interior_types = types;
184
-
185
- // Extract type components
186
- let type_list = fcx. tcx . mk_type_list ( folded_types. iter ( ) ) ;
187
188
189
+ // Extract type components to build the witness type.
190
+ let type_list = fcx. tcx . mk_type_list ( type_causes. iter ( ) . map ( |cause| cause. ty ) ) ;
188
191
let witness = fcx. tcx . mk_generator_witness ( ty:: Binder :: bind ( type_list) ) ;
189
192
193
+ // Store the generator types and spans into the tables for this generator.
194
+ visitor. fcx . inh . tables . borrow_mut ( ) . generator_interior_types = type_causes;
195
+
190
196
debug ! (
191
197
"types in generator after region replacement {:?}, span = {:?}" ,
192
198
witness, body. value. span
0 commit comments