Change:
} fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout { <del> let tcx = cx.tcx(); let tag_layout = |tag: &Scalar| -> C::TyAndLayout { let layout = Layout::scalar(cx, tag.clone()); MaybeResult::from(Ok(TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx), })) }; </del> <ins> enum TyMaybeWithLayout<C: LayoutOf> { Ty(C::Ty), TyAndLayout(C::TyAndLayout), } </ins> <del> cx.layout_of(match *this.ty.kind() { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::FnPtr(_) | ty::Never | ty::FnDef(..) | ty::GeneratorWitness(..) | ty::Foreign(..) | ty::Dynamic(..) => bug!("TyAndLayout::field_type({:?}): not applicable", this), // Potentially-fat pointers. ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { assert!(i < this.fields.count()); // Reuse the fat `*T` type as its own thin pointer data field. // This provides information about, e.g., DST struct pointees // (which may have no non-DST form), and will work as long // as the `Abi` or `FieldsShape` is checked by users. if i == 0 { let nil = tcx.mk_unit(); let ptr_ty = if this.ty.is_unsafe_ptr() { tcx.mk_mut_ptr(nil) } else { tcx.mk_mut_ref(tcx.lifetimes.re_static, nil) }; return MaybeResult::from(cx.layout_of(ptr_ty).to_result().map( |mut ptr_layout| { ptr_layout.ty = this.ty; ptr_layout }, )); } </del> <ins> fn ty_and_layout_kind< C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout: MaybeResult<TyAndLayout<'tcx>>> + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, >( this: TyAndLayout<'tcx>, cx: &C, i: usize, ty: C::Ty, ) -> TyMaybeWithLayout<C> { let tcx = cx.tcx(); let tag_layout = |tag: &Scalar| -> C::TyAndLayout { let layout = Layout::scalar(cx, tag.clone()); MaybeResult::from(Ok(TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx), })) }; </ins> <del> match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, ty::Dynamic(_, _) => { tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3)) /* FIXME: use actual fn pointers Warning: naively computing the number of entries in the vtable by counting the methods on the trait + methods on all parent traits does not work, because some methods can be not object safe and thus excluded from the vtable. Increase this counter if you tried to implement this but failed to do it without duplicating a lot of code from other places in the compiler: 2 tcx.mk_tup(&[ tcx.mk_array(tcx.types.usize, 3), tcx.mk_array(Option<fn()>), ]) */ </del> <ins> match *ty.kind() { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::FnPtr(_) | ty::Never | ty::FnDef(..) | ty::GeneratorWitness(..) | ty::Foreign(..) | ty::Dynamic(..) => bug!("TyAndLayout::field_type({:?}): not applicable", this), // Potentially-fat pointers. ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { assert!(i < this.fields.count()); // Reuse the fat `*T` type as its own thin pointer data field. // This provides information about, e.g., DST struct pointees // (which may have no non-DST form), and will work as long // as the `Abi` or `FieldsShape` is checked by users. if i == 0 { let nil = tcx.mk_unit(); let ptr_ty = if ty.is_unsafe_ptr() { tcx.mk_mut_ptr(nil) } else { tcx.mk_mut_ref(tcx.lifetimes.re_static, nil) }; return TyMaybeWithLayout::TyAndLayout(MaybeResult::from( cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| { ptr_layout.ty = ty; ptr_layout }), )); </ins> } <del> _ => bug!("TyAndLayout::field_type({:?}): not applicable", this), } } // Arrays and slices. ty::Array(element, _) | ty::Slice(element) => element, ty::Str => tcx.types.u8, // Tuples, generators and closures. ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().nth(i).unwrap(), ty::Generator(def_id, ref substs, _) => match this.variants { Variants::Single { index } => substs .as_generator() .state_tys(def_id, tcx) .nth(index.as_usize()) .unwrap() .nth(i) .unwrap(), Variants::Multiple { ref tag, tag_field, .. } => { if i == tag_field { return tag_layout(tag); </del> <ins> match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize), ty::Dynamic(_, _) => { TyMaybeWithLayout::Ty(tcx.mk_imm_ref( tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3), )) /* FIXME: use actual fn pointers Warning: naively computing the number of entries in the vtable by counting the methods on the trait + methods on all parent traits does not work, because some methods can be not object safe and thus excluded from the vtable. Increase this counter if you tried to implement this but failed to do it without duplicating a lot of code from other places in the compiler: 2 tcx.mk_tup(&[ tcx.mk_array(tcx.types.usize, 3), tcx.mk_array(Option<fn()>), ]) */ } _ => bug!("TyAndLayout::field_type({:?}): not applicable", this), </ins> } <del> substs.as_generator().prefix_tys().nth(i).unwrap() </del> } <del> }, ty::Tuple(tys) => tys[i].expect_ty(), </del> <ins> // Arrays and slices. ty::Array(element, _) | ty::Slice(element) => TyMaybeWithLayout::Ty(element), ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8), </ins> <del> // ADTs. ty::Adt(def, substs) => { match this.variants { Variants::Single { index } => def.variants[index].fields[i].ty(tcx, substs), </del> <ins> // Tuples, generators and closures. ty::Closure(_, ref substs) => { ty_and_layout_kind(this, cx, i, substs.as_closure().tupled_upvars_ty()) } ty::Generator(def_id, ref substs, _) => match this.variants { Variants::Single { index } => TyMaybeWithLayout::Ty( substs .as_generator() .state_tys(def_id, tcx) .nth(index.as_usize()) .unwrap() .nth(i) .unwrap(), ), Variants::Multiple { ref tag, tag_field, .. } => { if i == tag_field { return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); } TyMaybeWithLayout::Ty(substs.as_generator().prefix_tys().nth(i).unwrap()) } }, ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i].expect_ty()), // ADTs. ty::Adt(def, substs) => { match this.variants { Variants::Single { index } => { TyMaybeWithLayout::Ty(def.variants[index].fields[i].ty(tcx, substs)) } </ins> <del> // Discriminant field for enums (where applicable). Variants::Multiple { ref tag, .. } => { assert_eq!(i, 0); return tag_layout(tag); </del> <ins> // Discriminant field for enums (where applicable). Variants::Multiple { ref tag, .. } => { assert_eq!(i, 0); return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); } </ins> } } <ins> ty::Projection(_) | ty::Bound(..) | ty::Placeholder(..) | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error(_) => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty), </ins> } <ins> } </ins> <del> ty::Projection(_) | ty::Bound(..) | ty::Placeholder(..) | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error(_) => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty), </del> <ins> cx.layout_of(match ty_and_layout_kind(this, cx, i, this.ty) { TyMaybeWithLayout::Ty(result) => result, TyMaybeWithLayout::TyAndLayout(result) => return result, </ins> }) }

Discussion:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --<!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</detailsNOTE: The bug is found by our work-in-progress compiler testing tool Kira, and the test program is reduced/minimized by <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
does this still panic after ? That only merged a couple days ago so you'll need to update your version of nightly.
Hmm I checked and it does, and it also panics before. So probably unrelated? cc just in case
Note that this works fine on .
Sorry, I accidentally closed the issue. Yes, you are right. It still crashes on the latest nightly version. I have a cron job to update my rust version everyday.
I think we ended up (incorrectly) removing a check in We shouldn't be calling upvarsty if is . This is a separate issue than that was fixed in
claim