From 3b01da3f521a0639086aaf70363c8857cfa3b4ed Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 24 May 2024 22:36:10 -0700 Subject: [PATCH 1/2] Revert "Validate the special layout restriction on DynMetadata" This reverts commit d83f3ca8ca2d20eadf92a135a1a4b65ca91a24f6. --- compiler/rustc_mir_transform/src/validate.rs | 9 ------- library/core/src/ptr/metadata.rs | 27 ++++++-------------- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 66cc65de64709..3a2b2c5f3002d 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -685,15 +685,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { check_equal(self, location, *f_ty); } ty::Adt(adt_def, args) => { - // see - if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() { - self.fail( - location, - format!("You can't project to field {f:?} of `DynMetadata` because \ - layout is weird and thinks it doesn't have fields."), - ); - } - let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT); let Some(field) = adt_def.variant(var).fields.get(f) else { fail_out_of_bounds(self, location); diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index e501970b580de..eb815b6d822c5 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -178,8 +178,8 @@ impl Clone for PtrComponents { /// compare equal (since identical vtables can be deduplicated within a codegen unit). #[lang = "dyn_metadata"] pub struct DynMetadata { - _vtable_ptr: &'static VTable, - _phantom: crate::marker::PhantomData, + vtable_ptr: &'static VTable, + phantom: crate::marker::PhantomData, } extern "C" { @@ -191,17 +191,6 @@ extern "C" { } impl DynMetadata { - /// One of the things that rustc_middle does with this being a lang item is - /// give it `FieldsShape::Primitive`, which means that as far as codegen can - /// tell, it *is* a reference, and thus doesn't have any fields. - /// That means we can't use field access, and have to transmute it instead. - #[inline] - fn vtable_ptr(self) -> *const VTable { - // SAFETY: this layout assumption is hard-coded into the compiler. - // If it's somehow not a size match, the transmute will error. - unsafe { crate::mem::transmute::(self) } - } - /// Returns the size of the type associated with this vtable. #[inline] pub fn size_of(self) -> usize { @@ -210,7 +199,7 @@ impl DynMetadata { // `Send` part! // SAFETY: DynMetadata always contains a valid vtable pointer return unsafe { - crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) + crate::intrinsics::vtable_size(self.vtable_ptr as *const VTable as *const ()) }; } @@ -219,7 +208,7 @@ impl DynMetadata { pub fn align_of(self) -> usize { // SAFETY: DynMetadata always contains a valid vtable pointer return unsafe { - crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) + crate::intrinsics::vtable_align(self.vtable_ptr as *const VTable as *const ()) }; } @@ -237,7 +226,7 @@ unsafe impl Sync for DynMetadata {} impl fmt::Debug for DynMetadata { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("DynMetadata").field(&self.vtable_ptr()).finish() + f.debug_tuple("DynMetadata").field(&(self.vtable_ptr as *const VTable)).finish() } } @@ -259,7 +248,7 @@ impl Eq for DynMetadata {} impl PartialEq for DynMetadata { #[inline] fn eq(&self, other: &Self) -> bool { - crate::ptr::eq::(self.vtable_ptr(), other.vtable_ptr()) + crate::ptr::eq::(self.vtable_ptr, other.vtable_ptr) } } @@ -267,7 +256,7 @@ impl Ord for DynMetadata { #[inline] #[allow(ambiguous_wide_pointer_comparisons)] fn cmp(&self, other: &Self) -> crate::cmp::Ordering { - <*const VTable>::cmp(&self.vtable_ptr(), &other.vtable_ptr()) + (self.vtable_ptr as *const VTable).cmp(&(other.vtable_ptr as *const VTable)) } } @@ -281,6 +270,6 @@ impl PartialOrd for DynMetadata { impl Hash for DynMetadata { #[inline] fn hash(&self, hasher: &mut H) { - crate::ptr::hash::(self.vtable_ptr(), hasher) + crate::ptr::hash::(self.vtable_ptr, hasher) } } From daad14f4a3e8353795751927f4eed1b2dd30e5a2 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 24 May 2024 22:41:10 -0700 Subject: [PATCH 2/2] Remove the `DynMetadata` special case in layout --- compiler/rustc_middle/src/ty/layout.rs | 17 ++--------------- library/core/src/ptr/metadata.rs | 13 +++++++------ 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 60ce87440328b..4743f3119676c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -853,23 +853,10 @@ where // fall back to structurally deducing metadata. && !pointee.references_error() { - let metadata = tcx.normalize_erasing_regions( + tcx.normalize_erasing_regions( cx.param_env(), Ty::new_projection(tcx, metadata_def_id, [pointee]), - ); - - // Map `Metadata = DynMetadata` 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, args) = metadata.kind() - && Some(def.did()) == tcx.lang_items().dyn_metadata() - && args.type_at(0).is_trait() - { - mk_dyn_vtable() - } else { - metadata - } + ) } else { match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index eb815b6d822c5..fadd203632e83 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -177,17 +177,18 @@ impl Clone for PtrComponents { /// duplicated in multiple codegen units), and pointers to vtables of *different* types/traits can /// compare equal (since identical vtables can be deduplicated within a codegen unit). #[lang = "dyn_metadata"] +// codegen assumes it can treat this as a single pointer +#[repr(transparent)] pub struct DynMetadata { vtable_ptr: &'static VTable, phantom: crate::marker::PhantomData, } -extern "C" { - /// Opaque type for accessing vtables. - /// - /// Private implementation detail of `DynMetadata::size_of` etc. - /// There is conceptually not actually any Abstract Machine memory behind this pointer. - type VTable; +/// This is not really what's behind a vtable, but the codegen tests want the +/// pointers to get `dereferencable` metadata, for example, and there's currently +/// no way to get that with `extern type`, which would otherwise be nicer. +struct VTable { + _stub: usize, } impl DynMetadata {