diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ca1c30def7a..9c71e694f4c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2994,10 +2994,29 @@ pub struct UnsafetyCheckResult { pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>, } +newtype_index! { + pub struct GeneratorField { + derive [HashStable] + DEBUG_FORMAT = "_{}", + } +} + /// The layout of generator state #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct GeneratorLayout<'tcx> { - pub variant_fields: IndexVec>>, + /// The type of every local stored inside the generator. + pub field_tys: IndexVec>, + + /// Which of the above fields are in each variant. Note that one field may + /// be stored in multiple variants. + pub variant_fields: IndexVec>, + + /// Names and scopes of all the stored generator locals. + /// NOTE(tmandry) This is *strictly* a temporary hack for codegen + /// debuginfo generation, and will be removed at some point. + /// Do **NOT** use it for anything else, local information should not be + /// in the MIR, please rely on local crate HIR or other side-channels. + pub __local_debuginfo_codegen_only_do_not_use: IndexVec>, } #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] @@ -3186,7 +3205,9 @@ BraceStructTypeFoldableImpl! { BraceStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for GeneratorLayout<'tcx> { - variant_fields + field_tys, + variant_fields, + __local_debuginfo_codegen_only_do_not_use, } } @@ -3561,6 +3582,15 @@ impl<'tcx> TypeFoldable<'tcx> for Field { } } +impl<'tcx> TypeFoldable<'tcx> for GeneratorField { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self { + *self + } + fn super_visit_with>(&self, _: &mut V) -> bool { + false + } +} + impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { Constant { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 331c54d1d46..a41209496bd 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -483,7 +483,7 @@ impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> { #[inline] pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Range { // FIXME requires optimized MIR - let num_variants = self.state_tys(def_id, tcx).count(); + let num_variants = tcx.generator_layout(def_id).variant_fields.len(); (VariantIdx::new(0)..VariantIdx::new(num_variants)) } @@ -541,9 +541,12 @@ impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> { pub fn state_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> impl Iterator> + Captures<'gcx> + 'a> { - tcx.generator_layout(def_id) - .variant_fields.iter() - .map(move |v| v.iter().map(move |d| d.ty.subst(tcx, self.substs))) + let layout = tcx.generator_layout(def_id); + layout.variant_fields.iter().map(move |variant| { + variant.iter().map(move |field| { + layout.field_tys[*field].subst(tcx, self.substs) + }) + }) } /// This is the types of the fields of a generator which are not stored in a diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index b09fe827b24..5b18e821982 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1597,8 +1597,9 @@ impl<'tcx> VariantInfo<'tcx> { VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn => Some(variant.fields[i].ident.to_string()), VariantInfo::Generator(_, generator_layout, variant_index) => { - let variant_decls = &generator_layout.variant_fields[*variant_index]; - variant_decls[i.into()].name.map(|name| name.to_string()) + let field = generator_layout.variant_fields[*variant_index][i.into()]; + let decl = &generator_layout.__local_debuginfo_codegen_only_do_not_use[field]; + decl.name.map(|name| name.to_string()) } _ => None, }; diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index d524ec05462..fcf099235aa 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -663,12 +663,14 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( generator_layout.variant_fields.iter() .zip(state_tys) .enumerate() - .flat_map(move |(variant_idx, (decls, tys))| { + .flat_map(move |(variant_idx, (fields, tys))| { let variant_idx = Some(VariantIdx::from(variant_idx)); - decls.iter() + fields.iter() .zip(tys) .enumerate() - .filter_map(move |(i, (decl, ty))| { + .filter_map(move |(i, (field, ty))| { + let decl = &generator_layout. + __local_debuginfo_codegen_only_do_not_use[*field]; if let Some(name) = decl.name { let ty = fx.monomorphize(&ty); let (var_scope, var_span) = fx.debug_loc(mir::SourceInfo { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index d9496c8c20a..77bf789d2dd 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -555,15 +555,22 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Create a map from local indices to generator struct indices. // We also create a vector of the LocalDecls of these locals. - let (remap, vars) = live_decls.enumerate().map(|(idx, (local, var))| { - ((local, (var.ty, variant_index, idx)), var) - }).unzip(); + let mut remap = FxHashMap::default(); + let mut decls = IndexVec::new(); + for (idx, (local, var)) in live_decls.enumerate() { + remap.insert(local, (var.ty, variant_index, idx)); + decls.push(var); + } + let field_tys = decls.iter().map(|field| field.ty).collect::>(); // Put every var in each variant, for now. + let all_vars = (0..field_tys.len()).map(GeneratorField::from).collect(); let empty_variants = iter::repeat(IndexVec::new()).take(3); - let state_variants = iter::repeat(vars).take(suspending_blocks.count()); + let state_variants = iter::repeat(all_vars).take(suspending_blocks.count()); let layout = GeneratorLayout { - variant_fields: empty_variants.chain(state_variants).collect() + field_tys, + variant_fields: empty_variants.chain(state_variants).collect(), + __local_debuginfo_codegen_only_do_not_use: decls, }; (remap, layout, storage_liveness)