about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs52
1 files changed, 45 insertions, 7 deletions
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 9e0ca44d098..112f15c6f9e 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -670,13 +670,24 @@ where
                         });
                     }
 
-                    match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
-                        ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize),
-                        ty::Dynamic(_, _, ty::Dyn) => {
-                            TyMaybeWithLayout::Ty(tcx.mk_imm_ref(
+                    let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
+                        let metadata = tcx.normalize_erasing_regions(
+                            cx.param_env(),
+                            tcx.mk_projection(metadata_def_id, [pointee]),
+                        );
+
+                        // Map `Metadata = DynMetadata<dyn Trait>` back to a vtable, since it
+                        // offers better information than `std::ptr::metadata::VTable`,
+                        // and we rely on this layout information to trigger a panic in
+                        // `std::mem::uninitialized::<&dyn Trait>()`, for example.
+                        if let ty::Adt(def, substs) = metadata.kind()
+                            && Some(def.did()) == tcx.lang_items().dyn_metadata()
+                            && substs.type_at(0).is_trait()
+                        {
+                            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
@@ -690,9 +701,36 @@ where
                                 tcx.mk_array(Option<fn()>),
                             ])
                             */
+                        } else {
+                            metadata
                         }
-                        _ => bug!("TyAndLayout::field({:?}): not applicable", this),
-                    }
+                    } else {
+                        match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
+                            ty::Slice(_) | ty::Str => tcx.types.usize,
+                            ty::Dynamic(_, _, ty::Dyn) => {
+                                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({:?}): not applicable", this),
+                        }
+                    };
+
+                    TyMaybeWithLayout::Ty(metadata)
                 }
 
                 // Arrays and slices.