Skip to content

Commit b1e15fa

Browse files
committed
Parameterize DynMetadata over its dyn SomeTrait type
1 parent 696b239 commit b1e15fa

File tree

3 files changed

+73
-22
lines changed

3 files changed

+73
-22
lines changed

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2164,7 +2164,10 @@ impl<'tcx> TyS<'tcx> {
21642164
| ty::Tuple(..) => tcx.types.unit,
21652165

21662166
ty::Str | ty::Slice(_) => tcx.types.usize,
2167-
ty::Dynamic(..) => tcx.type_of(tcx.lang_items().dyn_metadata().unwrap()),
2167+
ty::Dynamic(..) => {
2168+
let dyn_metadata = tcx.lang_items().dyn_metadata().unwrap();
2169+
tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()])
2170+
},
21682171

21692172
ty::Projection(_)
21702173
| ty::Param(_)

library/core/src/ptr/metadata.rs

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
22

33
use crate::fmt;
4-
use crate::hash::Hash;
4+
use crate::hash::{Hash, Hasher};
55
use crate::ptr::NonNull;
66

77
/// FIXME docs
@@ -61,17 +61,60 @@ impl<T: ?Sized> Clone for PtrComponents<T> {
6161

6262
/// The metadata for a `dyn SomeTrait` trait object type.
6363
#[lang = "dyn_metadata"]
64-
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
65-
pub struct DynMetadata {
64+
pub struct DynMetadata<Dyn: ?Sized> {
6665
#[allow(unused)]
6766
vtable_ptr: NonNull<()>,
67+
phantom: crate::marker::PhantomData<Dyn>,
6868
}
6969

70-
unsafe impl Send for DynMetadata {}
71-
unsafe impl Sync for DynMetadata {}
70+
unsafe impl<Dyn: ?Sized> Send for DynMetadata<Dyn> {}
71+
unsafe impl<Dyn: ?Sized> Sync for DynMetadata<Dyn> {}
7272

73-
impl fmt::Debug for DynMetadata {
73+
impl<Dyn: ?Sized> fmt::Debug for DynMetadata<Dyn> {
7474
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7575
f.write_str("DynMetadata { … }")
7676
}
7777
}
78+
79+
// Manual impls needed to avoid `Dyn: $Trait` bounds.
80+
81+
impl<Dyn: ?Sized> Unpin for DynMetadata<Dyn> {}
82+
83+
impl<Dyn: ?Sized> Copy for DynMetadata<Dyn> {}
84+
85+
impl<Dyn: ?Sized> Clone for DynMetadata<Dyn> {
86+
#[inline]
87+
fn clone(&self) -> Self {
88+
*self
89+
}
90+
}
91+
92+
impl<Dyn: ?Sized> Eq for DynMetadata<Dyn> {}
93+
94+
impl<Dyn: ?Sized> PartialEq for DynMetadata<Dyn> {
95+
#[inline]
96+
fn eq(&self, other: &Self) -> bool {
97+
self.vtable_ptr == other.vtable_ptr
98+
}
99+
}
100+
101+
impl<Dyn: ?Sized> Ord for DynMetadata<Dyn> {
102+
#[inline]
103+
fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
104+
self.vtable_ptr.cmp(&other.vtable_ptr)
105+
}
106+
}
107+
108+
impl<Dyn: ?Sized> PartialOrd for DynMetadata<Dyn> {
109+
#[inline]
110+
fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
111+
Some(self.vtable_ptr.cmp(&other.vtable_ptr))
112+
}
113+
}
114+
115+
impl<Dyn: ?Sized> Hash for DynMetadata<Dyn> {
116+
#[inline]
117+
fn hash<H: Hasher>(&self, hasher: &mut H) {
118+
self.vtable_ptr.hash(hasher)
119+
}
120+
}

library/core/tests/ptr.rs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use core::cell::RefCell;
22
use core::ptr::*;
3-
use std::fmt::Display;
3+
use std::fmt::{Debug, Display};
44

55
#[test]
66
fn test_const_from_raw_parts() {
@@ -452,20 +452,25 @@ fn ptr_metadata() {
452452
assert_eq!(metadata(dst_struct), 3_usize);
453453
}
454454

455-
let vtable_1: DynMetadata = metadata(&4_u32 as &dyn Display);
456-
let vtable_2: DynMetadata = metadata(&(true, 7_u32) as &(bool, dyn Display));
457-
let vtable_3: DynMetadata = metadata(&Pair(true, 7_u32) as &Pair<bool, dyn Display>);
458-
let vtable_4: DynMetadata = metadata(&4_u16 as &dyn Display);
455+
let vtable_1: DynMetadata<dyn Debug> = metadata(&4_u16 as &dyn Debug);
456+
let vtable_2: DynMetadata<dyn Display> = metadata(&4_u16 as &dyn Display);
457+
let vtable_3: DynMetadata<dyn Display> = metadata(&4_u32 as &dyn Display);
458+
let vtable_4: DynMetadata<dyn Display> = metadata(&(true, 7_u32) as &(bool, dyn Display));
459+
let vtable_5: DynMetadata<dyn Display> =
460+
metadata(&Pair(true, 7_u32) as &Pair<bool, dyn Display>);
459461
unsafe {
460462
let address_1: usize = std::mem::transmute(vtable_1);
461463
let address_2: usize = std::mem::transmute(vtable_2);
462464
let address_3: usize = std::mem::transmute(vtable_3);
463465
let address_4: usize = std::mem::transmute(vtable_4);
464-
// Same erased type and same trait: same vtable pointer
465-
assert_eq!(address_1, address_2);
466-
assert_eq!(address_1, address_3);
467-
// Different erased type: different vtable pointer
468-
assert_ne!(address_1, address_4);
466+
let address_5: usize = std::mem::transmute(vtable_5);
467+
// Different trait => different vtable pointer
468+
assert_ne!(address_1, address_2);
469+
// Different erased type => different vtable pointer
470+
assert_ne!(address_2, address_3);
471+
// Same erased type and same trait => same vtable pointer
472+
assert_eq!(address_3, address_4);
473+
assert_eq!(address_3, address_5);
469474
}
470475
}
471476

@@ -486,11 +491,11 @@ fn ptr_metadata_bounds() {
486491

487492
// For this reason, let’s check here that bounds are satisfied:
488493

489-
static_assert_expected_bounds_for_metadata::<()>();
490-
static_assert_expected_bounds_for_metadata::<usize>();
491-
static_assert_expected_bounds_for_metadata::<DynMetadata>();
492-
fn static_assert_associated_type<T: ?Sized>() {
493-
static_assert_expected_bounds_for_metadata::<<T as Pointee>::Metadata>()
494+
let _ = static_assert_expected_bounds_for_metadata::<()>;
495+
let _ = static_assert_expected_bounds_for_metadata::<usize>;
496+
let _ = static_assert_expected_bounds_for_metadata::<DynMetadata<dyn Display>>;
497+
fn _static_assert_associated_type<T: ?Sized>() {
498+
let _ = static_assert_expected_bounds_for_metadata::<<T as Pointee>::Metadata>;
494499
}
495500

496501
fn static_assert_expected_bounds_for_metadata<Meta>()

0 commit comments

Comments
 (0)