33
33
/// those are embeddable in instruction encoding, for example:
34
34
///
35
35
/// ```asm
36
- /// // (https://godbolt.org/z/jqcYPWEr3)
36
+ /// // (< https://godbolt.org/z/jqcYPWEr3> )
37
37
/// example::shift_read3:
38
38
/// mov eax, dword ptr [8*rdi]
39
39
/// ret
49
49
/// - `shift_read3` uses `<< 3` (the tag is in the most-significant bits)
50
50
/// - `mask_read3` uses `& !0b111` (the tag is in the least-significant bits)
51
51
///
52
- /// The shift approach thus produces less instructions and is likely faster.
52
+ /// The shift approach thus produces less instructions and is likely faster
53
+ /// (see <https://godbolt.org/z/Y913sMdWb>).
53
54
///
54
55
/// Encoding diagram:
55
56
/// ```text
@@ -66,12 +67,21 @@ where
66
67
tag_ghost : PhantomData < T > ,
67
68
}
68
69
70
+ // Note that even though `CopyTaggedPtr` is only really expected to work with
71
+ // `P: Copy`, can't add `P: Copy` bound, because `CopyTaggedPtr` is used in the
72
+ // `TaggedPtr`'s implementation.
69
73
impl < P , T , const CP : bool > CopyTaggedPtr < P , T , CP >
70
74
where
71
75
P : Pointer ,
72
76
T : Tag ,
73
77
{
74
78
/// Tags `pointer` with `tag`.
79
+ ///
80
+ /// Note that this leaks `pointer`: it won't be dropped when
81
+ /// `CopyTaggedPtr` is dropped. If you have a pointer with a significant
82
+ /// drop, use [`TaggedPtr`] instead.
83
+ ///
84
+ /// [`TaggedPtr`]: crate::tagged_ptr::TaggedPtr
75
85
pub fn new ( pointer : P , tag : T ) -> Self {
76
86
Self { packed : Self :: pack ( P :: into_ptr ( pointer) , tag) , tag_ghost : PhantomData }
77
87
}
95
105
let tag = self . packed . addr ( ) . get ( ) >> Self :: TAG_BIT_SHIFT ;
96
106
97
107
// Safety:
98
- //
108
+ // The shift retrieves the original value from `T::into_usize`,
109
+ // satisfying `T::from_usize`'s preconditions.
99
110
unsafe { T :: from_usize ( tag) }
100
111
}
101
112
@@ -152,6 +163,10 @@ where
152
163
//
153
164
// Semantically this is just `f(&self.pointer)` (where `self.pointer`
154
165
// is non-packed original pointer).
166
+ //
167
+ // Note that even though `CopyTaggedPtr` is only really expected to
168
+ // work with `P: Copy`, we have to assume `P: ?Copy`, because
169
+ // `CopyTaggedPtr` is used in the `TaggedPtr`'s implementation.
155
170
let ptr = unsafe { ManuallyDrop :: new ( P :: from_ptr ( self . pointer_raw ( ) ) ) } ;
156
171
f ( & ptr)
157
172
}
0 commit comments