From 21dc49c587c7df282b8e96dc01c288c7d59bbd2c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 17 Jul 2024 13:49:32 +0200 Subject: [PATCH 1/2] ptr::metadata: avoid references to extern types --- library/core/src/ptr/metadata.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index eb86bf6620652..21d1b7ea0ce77 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -5,6 +5,7 @@ use crate::hash::{Hash, Hasher}; use crate::intrinsics::aggregate_raw_ptr; use crate::intrinsics::ptr_metadata; use crate::marker::Freeze; +use crate::ptr::NonNull; /// Provides the pointer metadata type of any pointed-to type. /// @@ -153,7 +154,7 @@ pub const fn from_raw_parts_mut( /// compare equal (since identical vtables can be deduplicated within a codegen unit). #[lang = "dyn_metadata"] pub struct DynMetadata { - _vtable_ptr: &'static VTable, + _vtable_ptr: NonNull, _phantom: crate::marker::PhantomData, } @@ -174,7 +175,7 @@ impl DynMetadata { 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) } + unsafe { crate::mem::transmute::(self) } } /// Returns the size of the type associated with this vtable. From f9c0d3370f04d08cda2da268a54bc543eb310fc7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 17 Jul 2024 13:50:17 +0200 Subject: [PATCH 2/2] ptr::metadata: update comment on vtable_ptr work-around --- library/core/src/ptr/metadata.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 21d1b7ea0ce77..06f205c0f2670 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -167,10 +167,13 @@ 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. + /// When `DynMetadata` appears as the metadata field of a wide pointer, the rustc_middle layout + /// computation does magic and the resulting layout is *not* a `FieldsShape::Aggregate`, instead + /// it is a `FieldsShape::Primitive`. This means that the same type can have different layout + /// depending on whether it appears as the metadata field of a wide pointer or as a stand-alone + /// type, which understandably confuses codegen and leads to ICEs when trying to project to a + /// field of `DynMetadata`. To work around that issue, we use `transmute` instead of using a + /// field projection. #[inline] fn vtable_ptr(self) -> *const VTable { // SAFETY: this layout assumption is hard-coded into the compiler.