Skip to content

Commit

Permalink
Fix async/await ICE rust-lang#64964
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkuu committed Oct 2, 2019
1 parent 7130fc5 commit 8e67180
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 9 deletions.
6 changes: 6 additions & 0 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,12 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
pub scope_span: Option<Span>,
}

BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for GeneratorInteriorTypeCause<'tcx> {
ty, span, scope_span
}
}

#[derive(RustcEncodable, RustcDecodable, Debug)]
pub struct TypeckTables<'tcx> {
/// The HirId::owner all ItemLocalIds in this table are relative to.
Expand Down
22 changes: 13 additions & 9 deletions src/librustc_typeck/check/generator_interior.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,6 @@ pub fn resolve_interior<'a, 'tcx>(
// Sort types by insertion order
types.sort_by_key(|t| t.1);

// Store the generator types and spans into the tables for this generator.
let interior_types = types.iter().cloned().map(|t| t.0).collect::<Vec<_>>();
visitor.fcx.inh.tables.borrow_mut().generator_interior_types = interior_types;

// Extract type components
let type_list = fcx.tcx.mk_type_list(types.into_iter().map(|t| (t.0).ty));

// The types in the generator interior contain lifetimes local to the generator itself,
// which should not be exposed outside of the generator. Therefore, we replace these
// lifetimes with existentially-bound lifetimes, which reflect the exact value of the
Expand All @@ -139,18 +132,29 @@ pub fn resolve_interior<'a, 'tcx>(
// if a Sync generator contains an &'α T, we need to check whether &'α T: Sync),
// so knowledge of the exact relationships between them isn't particularly important.

debug!("types in generator {:?}, span = {:?}", type_list, body.value.span);
debug!(
"types in generator {:?}, span = {:?}",
types.iter().map(|t| (t.0).ty).collect::<Vec<_>>(),
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 type_list = fcx.tcx.fold_regions(&type_list, &mut false, |_, current_depth| {
let types = fcx.tcx.fold_regions(&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 interior_types = types.iter().map(|t| t.0.clone()).collect::<Vec<_>>();
visitor.fcx.inh.tables.borrow_mut().generator_interior_types = interior_types;

// Extract type components
let type_list = fcx.tcx.mk_type_list(types.into_iter().map(|t| (t.0).ty));

let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));

debug!("types in generator after region replacement {:?}, span = {:?}",
Expand Down
22 changes: 22 additions & 0 deletions src/test/ui/async-await/issues/issue-64964.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// check-pass
// compile-flags: -Z query-dep-graph
// edition:2018

// Regression test for ICE related to `await`ing in a method. (#64964)

struct Body;
impl Body {
async fn next(&mut self) {
async {}.await
}
}

// Another reproduction: `await`ing with a variable from for-loop.

async fn bar() {
for x in 0..10 {
async { Some(x) }.await.unwrap();
}
}

fn main() {}

0 comments on commit 8e67180

Please sign in to comment.