]> git.proxmox.com Git - rustc.git/blob - src/librustc_data_structures/tagged_ptr/drop.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_data_structures / tagged_ptr / drop.rs
1 use super::{Pointer, Tag};
2 use crate::stable_hasher::{HashStable, StableHasher};
3 use std::fmt;
4
5 use super::CopyTaggedPtr;
6
7 /// A TaggedPtr implementing `Drop`.
8 ///
9 /// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without
10 /// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that,
11 /// wrap the TaggedPtr.
12 pub struct TaggedPtr<P, T, const COMPARE_PACKED: bool>
13 where
14 P: Pointer,
15 T: Tag,
16 {
17 raw: CopyTaggedPtr<P, T, COMPARE_PACKED>,
18 }
19
20 impl<P, T, const COMPARE_PACKED: bool> Clone for TaggedPtr<P, T, COMPARE_PACKED>
21 where
22 P: Pointer + Clone,
23 T: Tag,
24 {
25 fn clone(&self) -> Self {
26 unsafe { Self::new(P::with_ref(self.raw.pointer_raw(), |p| p.clone()), self.raw.tag()) }
27 }
28 }
29
30 // We pack the tag into the *upper* bits of the pointer to ease retrieval of the
31 // value; a right shift is a multiplication and those are embeddable in
32 // instruction encoding.
33 impl<P, T, const COMPARE_PACKED: bool> TaggedPtr<P, T, COMPARE_PACKED>
34 where
35 P: Pointer,
36 T: Tag,
37 {
38 pub fn new(pointer: P, tag: T) -> Self {
39 TaggedPtr { raw: CopyTaggedPtr::new(pointer, tag) }
40 }
41
42 pub fn pointer_ref(&self) -> &P::Target {
43 self.raw.pointer_ref()
44 }
45 pub fn pointer_mut(&mut self) -> &mut P::Target
46 where
47 P: std::ops::DerefMut,
48 {
49 self.raw.pointer_mut()
50 }
51 pub fn tag(&self) -> T {
52 self.raw.tag()
53 }
54 pub fn set_tag(&mut self, tag: T) {
55 self.raw.set_tag(tag);
56 }
57 }
58
59 impl<P, T, const COMPARE_PACKED: bool> std::ops::Deref for TaggedPtr<P, T, COMPARE_PACKED>
60 where
61 P: Pointer,
62 T: Tag,
63 {
64 type Target = P::Target;
65 fn deref(&self) -> &Self::Target {
66 self.raw.pointer_ref()
67 }
68 }
69
70 impl<P, T, const COMPARE_PACKED: bool> std::ops::DerefMut for TaggedPtr<P, T, COMPARE_PACKED>
71 where
72 P: Pointer + std::ops::DerefMut,
73 T: Tag,
74 {
75 fn deref_mut(&mut self) -> &mut Self::Target {
76 self.raw.pointer_mut()
77 }
78 }
79
80 impl<P, T, const COMPARE_PACKED: bool> Drop for TaggedPtr<P, T, COMPARE_PACKED>
81 where
82 P: Pointer,
83 T: Tag,
84 {
85 fn drop(&mut self) {
86 // No need to drop the tag, as it's Copy
87 unsafe {
88 std::mem::drop(P::from_usize(self.raw.pointer_raw()));
89 }
90 }
91 }
92
93 impl<P, T, const COMPARE_PACKED: bool> fmt::Debug for TaggedPtr<P, T, COMPARE_PACKED>
94 where
95 P: Pointer,
96 P::Target: fmt::Debug,
97 T: Tag + fmt::Debug,
98 {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 f.debug_struct("TaggedPtr")
101 .field("pointer", &self.pointer_ref())
102 .field("tag", &self.tag())
103 .finish()
104 }
105 }
106
107 impl<P, T> PartialEq for TaggedPtr<P, T, true>
108 where
109 P: Pointer,
110 T: Tag,
111 {
112 fn eq(&self, other: &Self) -> bool {
113 self.raw.eq(&other.raw)
114 }
115 }
116
117 impl<P, T> Eq for TaggedPtr<P, T, true>
118 where
119 P: Pointer,
120 T: Tag,
121 {
122 }
123
124 impl<P, T> std::hash::Hash for TaggedPtr<P, T, true>
125 where
126 P: Pointer,
127 T: Tag,
128 {
129 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
130 self.raw.hash(state);
131 }
132 }
133
134 impl<P, T, HCX, const COMPARE_PACKED: bool> HashStable<HCX> for TaggedPtr<P, T, COMPARE_PACKED>
135 where
136 P: Pointer + HashStable<HCX>,
137 T: Tag + HashStable<HCX>,
138 {
139 fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
140 self.raw.hash_stable(hcx, hasher);
141 }
142 }