1 use super::{Pointer, Tag}
;
2 use crate::stable_hasher
::{HashStable, StableHasher}
;
4 use std
::marker
::PhantomData
;
5 use std
::num
::NonZeroUsize
;
7 /// A `Copy` TaggedPtr.
9 /// You should use this instead of the `TaggedPtr` type in all cases where
12 /// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without
13 /// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that,
14 /// wrap the TaggedPtr.
15 pub struct CopyTaggedPtr
<P
, T
, const COMPARE_PACKED
: bool
>
21 data
: PhantomData
<(P
, T
)>,
24 impl<P
, T
, const COMPARE_PACKED
: bool
> Copy
for CopyTaggedPtr
<P
, T
, COMPARE_PACKED
>
32 impl<P
, T
, const COMPARE_PACKED
: bool
> Clone
for CopyTaggedPtr
<P
, T
, COMPARE_PACKED
>
38 fn clone(&self) -> Self {
43 // We pack the tag into the *upper* bits of the pointer to ease retrieval of the
44 // value; a left shift is a multiplication and those are embeddable in
45 // instruction encoding.
46 impl<P
, T
, const COMPARE_PACKED
: bool
> CopyTaggedPtr
<P
, T
, COMPARE_PACKED
>
51 const TAG_BIT_SHIFT
: usize = usize::BITS
as usize - T
::BITS
;
52 const ASSERTION
: () = {
53 assert
!(T
::BITS
<= P
::BITS
);
54 // Used for the transmute_copy's below
55 assert
!(std
::mem
::size_of
::<&P
::Target
>() == std
::mem
::size_of
::<usize>());
58 pub fn new(pointer
: P
, tag
: T
) -> Self {
60 let () = Self::ASSERTION
;
61 let packed_tag
= tag
.into_usize() << Self::TAG_BIT_SHIFT
;
64 // SAFETY: We know that the pointer is non-null, as it must be
65 // dereferenceable per `Pointer` safety contract.
67 NonZeroUsize
::new_unchecked((P
::into_usize(pointer
) >> T
::BITS
) | packed_tag
)
73 pub(super) fn pointer_raw(&self) -> usize {
74 self.packed
.get() << T
::BITS
76 pub fn pointer(self) -> P
80 // SAFETY: pointer_raw returns the original pointer
82 // Note that this isn't going to double-drop or anything because we have
84 unsafe { P::from_usize(self.pointer_raw()) }
86 pub fn pointer_ref(&self) -> &P
::Target
{
87 // SAFETY: pointer_raw returns the original pointer
88 unsafe { std::mem::transmute_copy(&self.pointer_raw()) }
90 pub fn pointer_mut(&mut self) -> &mut P
::Target
92 P
: std
::ops
::DerefMut
,
94 // SAFETY: pointer_raw returns the original pointer
95 unsafe { std::mem::transmute_copy(&self.pointer_raw()) }
98 pub fn tag(&self) -> T
{
99 unsafe { T::from_usize(self.packed.get() >> Self::TAG_BIT_SHIFT) }
102 pub fn set_tag(&mut self, tag
: T
) {
103 let mut packed
= self.packed
.get();
104 let new_tag
= T
::into_usize(tag
) << Self::TAG_BIT_SHIFT
;
105 let tag_mask
= (1 << T
::BITS
) - 1;
106 packed
&= !(tag_mask
<< Self::TAG_BIT_SHIFT
);
108 self.packed
= unsafe { NonZeroUsize::new_unchecked(packed) }
;
112 impl<P
, T
, const COMPARE_PACKED
: bool
> std
::ops
::Deref
for CopyTaggedPtr
<P
, T
, COMPARE_PACKED
>
117 type Target
= P
::Target
;
118 fn deref(&self) -> &Self::Target
{
123 impl<P
, T
, const COMPARE_PACKED
: bool
> std
::ops
::DerefMut
for CopyTaggedPtr
<P
, T
, COMPARE_PACKED
>
125 P
: Pointer
+ std
::ops
::DerefMut
,
128 fn deref_mut(&mut self) -> &mut Self::Target
{
133 impl<P
, T
, const COMPARE_PACKED
: bool
> fmt
::Debug
for CopyTaggedPtr
<P
, T
, COMPARE_PACKED
>
136 P
::Target
: fmt
::Debug
,
139 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
140 f
.debug_struct("CopyTaggedPtr")
141 .field("pointer", &self.pointer_ref())
142 .field("tag", &self.tag())
147 impl<P
, T
> PartialEq
for CopyTaggedPtr
<P
, T
, true>
152 fn eq(&self, other
: &Self) -> bool
{
153 self.packed
== other
.packed
157 impl<P
, T
> Eq
for CopyTaggedPtr
<P
, T
, true>
164 impl<P
, T
> std
::hash
::Hash
for CopyTaggedPtr
<P
, T
, true>
169 fn hash
<H
: std
::hash
::Hasher
>(&self, state
: &mut H
) {
170 self.packed
.hash(state
);
174 impl<P
, T
, HCX
, const COMPARE_PACKED
: bool
> HashStable
<HCX
> for CopyTaggedPtr
<P
, T
, COMPARE_PACKED
>
176 P
: Pointer
+ HashStable
<HCX
>,
177 T
: Tag
+ HashStable
<HCX
>,
179 fn hash_stable(&self, hcx
: &mut HCX
, hasher
: &mut StableHasher
) {
181 Pointer
::with_ref(self.pointer_raw(), |p
: &P
| p
.hash_stable(hcx
, hasher
));
183 self.tag().hash_stable(hcx
, hasher
);