Skip to content

Commit 791123d

Browse files
Deduplicate generator interior types
1 parent eed12bc commit 791123d

File tree

3 files changed

+30
-24
lines changed

3 files changed

+30
-24
lines changed

src/librustc_typeck/check/generator_interior.rs

+27-21
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::FnCtxt;
77
use rustc::hir::map::Map;
88
use rustc::middle::region::{self, YieldData};
99
use rustc::ty::{self, Ty};
10-
use rustc_data_structures::fx::FxHashMap;
10+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1111
use rustc_hir as hir;
1212
use rustc_hir::def::{CtorKind, DefKind, Res};
1313
use rustc_hir::def_id::DefId;
@@ -160,33 +160,39 @@ pub fn resolve_interior<'a, 'tcx>(
160160

161161
debug!("types in generator {:?}, span = {:?}", types, body.value.span);
162162

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.
167163
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
176166
.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+
}
181186
})
182187
.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());
187188

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));
188191
let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
189192

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+
190196
debug!(
191197
"types in generator after region replacement {:?}, span = {:?}",
192198
witness, body.value.span

src/test/ui/generator/not-send-sync.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ LL | fn assert_sync<T: Sync>(_: T) {}
2020
LL | assert_sync(|| {
2121
| ^^^^^^^^^^^ future returned by `main` is not `Sync`
2222
|
23-
= help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, (), ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
23+
= help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
2424
note: future is not `Sync` as this value is used across an yield
2525
--> $DIR/not-send-sync.rs:12:9
2626
|

src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ error[E0720]: opaque type expands to a recursive type
7676
LL | fn generator_capture() -> impl Sized {
7777
| ^^^^^^^^^^ expands to a recursive type
7878
|
79-
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {(), ()}]`
79+
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {()}]`
8080

8181
error[E0720]: opaque type expands to a recursive type
8282
--> $DIR/recursive-impl-trait-type-indirect.rs:53:26
@@ -92,7 +92,7 @@ error[E0720]: opaque type expands to a recursive type
9292
LL | fn generator_hold() -> impl Sized {
9393
| ^^^^^^^^^^ expands to a recursive type
9494
|
95-
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, (), ()}]`
95+
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, ()}]`
9696

9797
error[E0720]: opaque type expands to a recursive type
9898
--> $DIR/recursive-impl-trait-type-indirect.rs:69:26

0 commit comments

Comments
 (0)