diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 7b993279f18e8..b7ffb4a16fc31 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -373,7 +373,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let (Some(caller), Some(callee)) = (pointee_ty(caller.ty)?, pointee_ty(callee.ty)?) { // This is okay if they have the same metadata type. let meta_ty = |ty: Ty<'tcx>| { - let (meta, only_if_sized) = ty.ptr_metadata_ty(*self.tcx, |ty| ty); + // Even if `ty` is normalized, the search for the unsized tail will project + // to fields, which can yield non-normalized types. So we need to provide a + // normalization function. + let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty); + let (meta, only_if_sized) = ty.ptr_metadata_ty(*self.tcx, normalize); assert!( !only_if_sized, "there should be no more 'maybe has that metadata' types during interpretation" diff --git a/src/tools/miri/tests/pass/issues/issue-miri-3282-struct-tail-normalize.rs b/src/tools/miri/tests/pass/issues/issue-miri-3282-struct-tail-normalize.rs new file mode 100644 index 0000000000000..2a31df83843e6 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-miri-3282-struct-tail-normalize.rs @@ -0,0 +1,20 @@ +// regression test for an ICE: https://github.com/rust-lang/miri/issues/3282 + +trait Id { + type Assoc: ?Sized; +} + +impl Id for T { + type Assoc = T; +} + +#[repr(transparent)] +struct Foo { + field: ::Assoc, +} + +fn main() { + let x = unsafe { std::mem::transmute::)>(|_| ()) }; + let foo: &Foo = unsafe { &*("uwu" as *const str as *const Foo) }; + x(foo); +}