diff options
Diffstat (limited to 'library')
| -rw-r--r-- | library/core/src/ptr/metadata.rs | 55 | ||||
| -rw-r--r-- | library/core/tests/ptr.rs | 35 |
2 files changed, 69 insertions, 21 deletions
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 416b1b860ce..948d7f0b039 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -1,7 +1,7 @@ #![unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")] use crate::fmt; -use crate::hash::Hash; +use crate::hash::{Hash, Hasher}; use crate::ptr::NonNull; /// FIXME docs @@ -61,17 +61,60 @@ impl<T: ?Sized> Clone for PtrComponents<T> { /// The metadata for a `dyn SomeTrait` trait object type. #[lang = "dyn_metadata"] -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] -pub struct DynMetadata { +pub struct DynMetadata<Dyn: ?Sized> { #[allow(unused)] vtable_ptr: NonNull<()>, + phantom: crate::marker::PhantomData<Dyn>, } -unsafe impl Send for DynMetadata {} -unsafe impl Sync for DynMetadata {} +unsafe impl<Dyn: ?Sized> Send for DynMetadata<Dyn> {} +unsafe impl<Dyn: ?Sized> Sync for DynMetadata<Dyn> {} -impl fmt::Debug for DynMetadata { +impl<Dyn: ?Sized> fmt::Debug for DynMetadata<Dyn> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("DynMetadata { … }") } } + +// Manual impls needed to avoid `Dyn: $Trait` bounds. + +impl<Dyn: ?Sized> Unpin for DynMetadata<Dyn> {} + +impl<Dyn: ?Sized> Copy for DynMetadata<Dyn> {} + +impl<Dyn: ?Sized> Clone for DynMetadata<Dyn> { + #[inline] + fn clone(&self) -> Self { + *self + } +} + +impl<Dyn: ?Sized> Eq for DynMetadata<Dyn> {} + +impl<Dyn: ?Sized> PartialEq for DynMetadata<Dyn> { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.vtable_ptr == other.vtable_ptr + } +} + +impl<Dyn: ?Sized> Ord for DynMetadata<Dyn> { + #[inline] + fn cmp(&self, other: &Self) -> crate::cmp::Ordering { + self.vtable_ptr.cmp(&other.vtable_ptr) + } +} + +impl<Dyn: ?Sized> PartialOrd for DynMetadata<Dyn> { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> { + Some(self.vtable_ptr.cmp(&other.vtable_ptr)) + } +} + +impl<Dyn: ?Sized> Hash for DynMetadata<Dyn> { + #[inline] + fn hash<H: Hasher>(&self, hasher: &mut H) { + self.vtable_ptr.hash(hasher) + } +} diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 03d2be725ef..ff3db740dfd 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -1,6 +1,6 @@ use core::cell::RefCell; use core::ptr::*; -use std::fmt::Display; +use std::fmt::{Debug, Display}; #[test] fn test_const_from_raw_parts() { @@ -452,20 +452,25 @@ fn ptr_metadata() { assert_eq!(metadata(dst_struct), 3_usize); } - let vtable_1: DynMetadata = metadata(&4_u32 as &dyn Display); - let vtable_2: DynMetadata = metadata(&(true, 7_u32) as &(bool, dyn Display)); - let vtable_3: DynMetadata = metadata(&Pair(true, 7_u32) as &Pair<bool, dyn Display>); - let vtable_4: DynMetadata = metadata(&4_u16 as &dyn Display); + let vtable_1: DynMetadata<dyn Debug> = metadata(&4_u16 as &dyn Debug); + let vtable_2: DynMetadata<dyn Display> = metadata(&4_u16 as &dyn Display); + let vtable_3: DynMetadata<dyn Display> = metadata(&4_u32 as &dyn Display); + let vtable_4: DynMetadata<dyn Display> = metadata(&(true, 7_u32) as &(bool, dyn Display)); + let vtable_5: DynMetadata<dyn Display> = + metadata(&Pair(true, 7_u32) as &Pair<bool, dyn Display>); unsafe { let address_1: usize = std::mem::transmute(vtable_1); let address_2: usize = std::mem::transmute(vtable_2); let address_3: usize = std::mem::transmute(vtable_3); let address_4: usize = std::mem::transmute(vtable_4); - // Same erased type and same trait: same vtable pointer - assert_eq!(address_1, address_2); - assert_eq!(address_1, address_3); - // Different erased type: different vtable pointer - assert_ne!(address_1, address_4); + let address_5: usize = std::mem::transmute(vtable_5); + // Different trait => different vtable pointer + assert_ne!(address_1, address_2); + // Different erased type => different vtable pointer + assert_ne!(address_2, address_3); + // Same erased type and same trait => same vtable pointer + assert_eq!(address_3, address_4); + assert_eq!(address_3, address_5); } } @@ -486,11 +491,11 @@ fn ptr_metadata_bounds() { // For this reason, let’s check here that bounds are satisfied: - static_assert_expected_bounds_for_metadata::<()>(); - static_assert_expected_bounds_for_metadata::<usize>(); - static_assert_expected_bounds_for_metadata::<DynMetadata>(); - fn static_assert_associated_type<T: ?Sized>() { - static_assert_expected_bounds_for_metadata::<<T as Pointee>::Metadata>() + let _ = static_assert_expected_bounds_for_metadata::<()>; + let _ = static_assert_expected_bounds_for_metadata::<usize>; + let _ = static_assert_expected_bounds_for_metadata::<DynMetadata<dyn Display>>; + fn _static_assert_associated_type<T: ?Sized>() { + let _ = static_assert_expected_bounds_for_metadata::<<T as Pointee>::Metadata>; } fn static_assert_expected_bounds_for_metadata<Meta>() |
