From 5ea1d0e865e3a15c054233198622b711ed0b5f86 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 14 Jan 2021 00:00:00 +0000 Subject: [PATCH] Don't ICE when computing a layout of a generator tainted by errors --- .../src/debuginfo/metadata.rs | 5 ++-- compiler/rustc_middle/src/ty/layout.rs | 6 ++-- compiler/rustc_middle/src/ty/mod.rs | 6 ++-- compiler/rustc_middle/src/ty/sty.rs | 4 +-- src/test/ui/generator/layout-error.rs | 28 +++++++++++++++++++ src/test/ui/generator/layout-error.stderr | 9 ++++++ 6 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/generator/layout-error.rs create mode 100644 src/test/ui/generator/layout-error.stderr diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 36a21b38c03..b9ae7963250 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1832,8 +1832,9 @@ fn field_name(&self, i: usize) -> String { fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option> { match self { VariantInfo::Generator { def_id, variant_index, .. } => { - let span = - cx.tcx.generator_layout(*def_id).variant_source_info[*variant_index].span; + let span = cx.tcx.generator_layout(*def_id).unwrap().variant_source_info + [*variant_index] + .span; if !span.is_dummy() { let loc = cx.lookup_debug_loc(span.lo()); return Some(SourceInfo { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4475d4e9f2d..195e840866a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1466,10 +1466,12 @@ fn generator_layout( ) -> Result<&'tcx Layout, LayoutError<'tcx>> { use SavedLocalEligibility::*; let tcx = self.tcx; - let subst_field = |ty: Ty<'tcx>| ty.subst(tcx, substs); - let info = tcx.generator_layout(def_id); + let info = match tcx.generator_layout(def_id) { + None => return Err(LayoutError::Unknown(ty)), + Some(info) => info, + }; let (ineligible_locals, assignments) = self.generator_saved_local_eligibility(&info); // Build a prefix layout, including "promoting" all ineligible diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8068574a38f..1399fc76e02 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -3068,8 +3068,10 @@ pub fn trait_is_auto(self, trait_def_id: DefId) -> bool { self.trait_def(trait_def_id).has_auto_impl } - pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'tcx> { - self.optimized_mir(def_id).generator_layout.as_ref().unwrap() + /// Returns layout of a generator. Layout might be unavailable if the + /// generator is tainted by errors. + pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> { + self.optimized_mir(def_id).generator_layout.as_ref() } /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 744c7a541a5..d43c5135d90 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -605,7 +605,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { #[inline] pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range { // FIXME requires optimized MIR - let num_variants = tcx.generator_layout(def_id).variant_fields.len(); + let num_variants = tcx.generator_layout(def_id).unwrap().variant_fields.len(); VariantIdx::new(0)..VariantIdx::new(num_variants) } @@ -666,7 +666,7 @@ pub fn state_tys( def_id: DefId, tcx: TyCtxt<'tcx>, ) -> impl Iterator> + Captures<'tcx>> { - let layout = tcx.generator_layout(def_id); + let layout = tcx.generator_layout(def_id).unwrap(); layout.variant_fields.iter().map(move |variant| { variant.iter().map(move |field| layout.field_tys[*field].subst(tcx, self.substs)) }) diff --git a/src/test/ui/generator/layout-error.rs b/src/test/ui/generator/layout-error.rs new file mode 100644 index 00000000000..059867277ad --- /dev/null +++ b/src/test/ui/generator/layout-error.rs @@ -0,0 +1,28 @@ +// Verifies that computing a layout of a generator tainted by type errors +// doesn't ICE. Regression test for #80998. +// +// edition:2018 + +#![feature(type_alias_impl_trait)] +use std::future::Future; + +pub struct Task(F); +impl Task { + fn new() -> Self { + todo!() + } + fn spawn(&self, _: impl FnOnce() -> F) { + todo!() + } +} + +fn main() { + async fn cb() { + let a = Foo; //~ ERROR cannot find value `Foo` in this scope + } + + type F = impl Future; + // Check that statics are inhabited computes they layout. + static POOL: Task = Task::new(); + Task::spawn(&POOL, || cb()); +} diff --git a/src/test/ui/generator/layout-error.stderr b/src/test/ui/generator/layout-error.stderr new file mode 100644 index 00000000000..b1a258f4f2c --- /dev/null +++ b/src/test/ui/generator/layout-error.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `Foo` in this scope + --> $DIR/layout-error.rs:21:17 + | +LL | let a = Foo; + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. -- 2.44.0