Skip to content

Commit d83f3ca

Browse files
committed
Validate the special layout restriction on DynMetadata
1 parent 5baee04 commit d83f3ca

2 files changed

Lines changed: 28 additions & 8 deletions

File tree

‎compiler/rustc_const_eval/src/transform/validate.rs‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
685685
check_equal(self, location,*f_ty);
686686
}
687687
ty::Adt(adt_def, args) => {
688+
// see <https://github.com/rust-lang/rust/blob/7601adcc764d42c9f2984082b49948af652df986/compiler/rustc_middle/src/ty/layout.rs#L861-L864>
689+
ifSome(adt_def.did()) == self.tcx.lang_items().dyn_metadata(){
690+
self.fail(
691+
location,
692+
format!("You can't project to field {f:?} of `DynMetadata` because \
693+
layout is weird and thinks it doesn't have fields."),
694+
);
695+
}
696+
688697
let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
689698
letSome(field) = adt_def.variant(var).fields.get(f)else{
690699
fail_out_of_bounds(self, location);

‎library/core/src/ptr/metadata.rs‎

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ impl<T: ?Sized> Clone for PtrComponents<T> {
178178
/// compare equal (since identical vtables can be deduplicated within a codegen unit).
179179
#[lang = "dyn_metadata"]
180180
pubstructDynMetadata<Dyn: ?Sized>{
181-
vtable_ptr:&'staticVTable,
182-
phantom:crate::marker::PhantomData<Dyn>,
181+
_vtable_ptr:&'staticVTable,
182+
_phantom:crate::marker::PhantomData<Dyn>,
183183
}
184184

185185
extern"C"{
@@ -191,6 +191,17 @@ extern "C" {
191191
}
192192

193193
impl<Dyn: ?Sized>DynMetadata<Dyn>{
194+
/// One of the things that rustc_middle does with this being a lang item is
195+
/// give it `FieldsShape::Primitive`, which means that as far as codegen can
196+
/// tell, it *is* a reference, and thus doesn't have any fields.
197+
/// That means we can't use field access, and have to transmute it instead.
198+
#[inline]
199+
fnvtable_ptr(self) -> *constVTable{
200+
// SAFETY: this layout assumption is hard-coded into the compiler.
201+
// If it's somehow not a size match, the transmute will error.
202+
unsafe{crate::mem::transmute::<Self,&'staticVTable>(self)}
203+
}
204+
194205
/// Returns the size of the type associated with this vtable.
195206
#[inline]
196207
pubfnsize_of(self) -> usize{
@@ -199,7 +210,7 @@ impl<Dyn: ?Sized> DynMetadata<Dyn> {
199210
// `Send` part!
200211
// SAFETY: DynMetadata always contains a valid vtable pointer
201212
returnunsafe{
202-
crate::intrinsics::vtable_size(self.vtable_ptras*constVTableas*const())
213+
crate::intrinsics::vtable_size(self.vtable_ptr()as*const())
203214
};
204215
}
205216

@@ -208,7 +219,7 @@ impl<Dyn: ?Sized> DynMetadata<Dyn> {
208219
pubfnalign_of(self) -> usize{
209220
// SAFETY: DynMetadata always contains a valid vtable pointer
210221
returnunsafe{
211-
crate::intrinsics::vtable_align(self.vtable_ptras*constVTableas*const())
222+
crate::intrinsics::vtable_align(self.vtable_ptr()as*const())
212223
};
213224
}
214225

@@ -226,7 +237,7 @@ unsafe impl<Dyn: ?Sized> Sync for DynMetadata<Dyn> {}
226237

227238
impl<Dyn: ?Sized> fmt::DebugforDynMetadata<Dyn>{
228239
fnfmt(&self,f:&mut fmt::Formatter<'_>) -> fmt::Result{
229-
f.debug_tuple("DynMetadata").field(&(self.vtable_ptras*constVTable)).finish()
240+
f.debug_tuple("DynMetadata").field(&self.vtable_ptr()).finish()
230241
}
231242
}
232243

@@ -248,15 +259,15 @@ impl<Dyn: ?Sized> Eq for DynMetadata<Dyn> {}
248259
impl<Dyn: ?Sized>PartialEqforDynMetadata<Dyn>{
249260
#[inline]
250261
fneq(&self,other:&Self) -> bool{
251-
crate::ptr::eq::<VTable>(self.vtable_ptr, other.vtable_ptr)
262+
crate::ptr::eq::<VTable>(self.vtable_ptr(), other.vtable_ptr())
252263
}
253264
}
254265

255266
impl<Dyn: ?Sized>OrdforDynMetadata<Dyn>{
256267
#[inline]
257268
#[allow(ambiguous_wide_pointer_comparisons)]
258269
fncmp(&self,other:&Self) -> crate::cmp::Ordering{
259-
(self.vtable_ptras*constVTable).cmp(&(other.vtable_ptras*constVTable))
270+
<*constVTable>::cmp(&self.vtable_ptr(),&other.vtable_ptr())
260271
}
261272
}
262273

@@ -270,6 +281,6 @@ impl<Dyn: ?Sized> PartialOrd for DynMetadata<Dyn> {
270281
impl<Dyn: ?Sized>HashforDynMetadata<Dyn>{
271282
#[inline]
272283
fnhash<H:Hasher>(&self,hasher:&mutH){
273-
crate::ptr::hash::<VTable,_>(self.vtable_ptr, hasher)
284+
crate::ptr::hash::<VTable,_>(self.vtable_ptr(), hasher)
274285
}
275286
}

0 commit comments

Comments
 (0)