Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deduplicate types in the generator witness #68672

Merged
merged 1 commit into from
Feb 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 27 additions & 21 deletions src/librustc_typeck/check/generator_interior.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::FnCtxt;
use rustc::hir::map::Map;
use rustc::middle::region::{self, YieldData};
use rustc::ty::{self, Ty};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
Expand Down Expand Up @@ -160,33 +160,39 @@ pub fn resolve_interior<'a, 'tcx>(

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

// Replace all regions inside the generator interior with late bound regions
// Note that each region slot in the types gets a new fresh late bound region,
// which means that none of the regions inside relate to any other, even if
// typeck had previously found constraints that would cause them to be related.
let mut counter = 0;
let fold_types: Vec<_> = types.iter().map(|(t, _)| t.ty).collect();
let folded_types = fcx.tcx.fold_regions(&fold_types, &mut false, |_, current_depth| {
counter += 1;
fcx.tcx.mk_region(ty::ReLateBound(current_depth, ty::BrAnon(counter)))
});

// Store the generator types and spans into the tables for this generator.
let types = types
let mut captured_tys = FxHashSet::default();
let type_causes: Vec<_> = types
.into_iter()
.zip(&folded_types)
.map(|((mut interior_cause, _), ty)| {
interior_cause.ty = ty;
interior_cause
.filter_map(|(mut cause, _)| {
// Erase regions and canonicalize late-bound regions to deduplicate as many types as we
// can.
let erased = fcx.tcx.erase_regions(&cause.ty);
if captured_tys.insert(erased) {
// Replace all regions inside the generator interior with late bound regions.
// Note that each region slot in the types gets a new fresh late bound region,
// which means that none of the regions inside relate to any other, even if
// typeck had previously found constraints that would cause them to be related.
let folded = fcx.tcx.fold_regions(&erased, &mut false, |_, current_depth| {
counter += 1;
fcx.tcx.mk_region(ty::ReLateBound(current_depth, ty::BrAnon(counter)))
});

cause.ty = folded;
Some(cause)
} else {
None
}
})
.collect();
visitor.fcx.inh.tables.borrow_mut().generator_interior_types = types;

// Extract type components
let type_list = fcx.tcx.mk_type_list(folded_types.iter());

// Extract type components to build the witness type.
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));

// Store the generator types and spans into the tables for this generator.
visitor.fcx.inh.tables.borrow_mut().generator_interior_types = type_causes;

debug!(
"types in generator after region replacement {:?}, span = {:?}",
witness, body.value.span
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/generator/not-send-sync.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ LL | fn assert_sync<T: Sync>(_: T) {}
LL | assert_sync(|| {
| ^^^^^^^^^^^ future returned by `main` is not `Sync`
|
= 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>`
= 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>`
note: future is not `Sync` as this value is used across an yield
--> $DIR/not-send-sync.rs:12:9
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ error[E0720]: opaque type expands to a recursive type
LL | fn generator_capture() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {(), ()}]`
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {()}]`

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

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