]>
Commit | Line | Data |
---|---|---|
1 | use crate::cmp::Ordering; | |
2 | use crate::convert::From; | |
3 | use crate::fmt; | |
4 | use crate::hash; | |
5 | use crate::marker::Unsize; | |
6 | use crate::mem; | |
7 | use crate::ops::{CoerceUnsized, DispatchFromDyn}; | |
8 | use crate::ptr::Unique; | |
9 | ||
10 | // ignore-tidy-undocumented-unsafe | |
11 | ||
12 | /// `*mut T` but non-zero and covariant. | |
13 | /// | |
14 | /// This is often the correct thing to use when building data structures using | |
15 | /// raw pointers, but is ultimately more dangerous to use because of its additional | |
16 | /// properties. If you're not sure if you should use `NonNull<T>`, just use `*mut T`! | |
17 | /// | |
18 | /// Unlike `*mut T`, the pointer must always be non-null, even if the pointer | |
19 | /// is never dereferenced. This is so that enums may use this forbidden value | |
20 | /// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`. | |
21 | /// However the pointer may still dangle if it isn't dereferenced. | |
22 | /// | |
23 | /// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect | |
24 | /// for your use case, you should include some [`PhantomData`] in your type to | |
25 | /// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`. | |
26 | /// Usually this won't be necessary; covariance is correct for most safe abstractions, | |
27 | /// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they | |
28 | /// provide a public API that follows the normal shared XOR mutable rules of Rust. | |
29 | /// | |
30 | /// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does | |
31 | /// not change the fact that mutating through a (pointer derived from a) shared | |
32 | /// reference is undefined behavior unless the mutation happens inside an | |
33 | /// [`UnsafeCell<T>`]. The same goes for creating a mutable reference from a shared | |
34 | /// reference. When using this `From` instance without an `UnsafeCell<T>`, | |
35 | /// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr` | |
36 | /// is never used for mutation. | |
37 | /// | |
38 | /// [`PhantomData`]: ../marker/struct.PhantomData.html | |
39 | /// [`UnsafeCell<T>`]: ../cell/struct.UnsafeCell.html | |
40 | #[stable(feature = "nonnull", since = "1.25.0")] | |
41 | #[repr(transparent)] | |
42 | #[rustc_layout_scalar_valid_range_start(1)] | |
43 | #[rustc_nonnull_optimization_guaranteed] | |
44 | pub struct NonNull<T: ?Sized> { | |
45 | pointer: *const T, | |
46 | } | |
47 | ||
48 | /// `NonNull` pointers are not `Send` because the data they reference may be aliased. | |
49 | // N.B., this impl is unnecessary, but should provide better error messages. | |
50 | #[stable(feature = "nonnull", since = "1.25.0")] | |
51 | impl<T: ?Sized> !Send for NonNull<T> {} | |
52 | ||
53 | /// `NonNull` pointers are not `Sync` because the data they reference may be aliased. | |
54 | // N.B., this impl is unnecessary, but should provide better error messages. | |
55 | #[stable(feature = "nonnull", since = "1.25.0")] | |
56 | impl<T: ?Sized> !Sync for NonNull<T> {} | |
57 | ||
58 | impl<T: Sized> NonNull<T> { | |
59 | /// Creates a new `NonNull` that is dangling, but well-aligned. | |
60 | /// | |
61 | /// This is useful for initializing types which lazily allocate, like | |
62 | /// `Vec::new` does. | |
63 | /// | |
64 | /// Note that the pointer value may potentially represent a valid pointer to | |
65 | /// a `T`, which means this must not be used as a "not yet initialized" | |
66 | /// sentinel value. Types that lazily allocate must track initialization by | |
67 | /// some other means. | |
68 | #[stable(feature = "nonnull", since = "1.25.0")] | |
69 | #[cfg_attr( | |
70 | not(bootstrap), | |
71 | rustc_const_stable(feature = "const_nonnull_dangling", since = "1.32.0"), | |
72 | )] | |
73 | #[inline] | |
74 | pub const fn dangling() -> Self { | |
75 | unsafe { | |
76 | let ptr = mem::align_of::<T>() as *mut T; | |
77 | NonNull::new_unchecked(ptr) | |
78 | } | |
79 | } | |
80 | } | |
81 | ||
82 | impl<T: ?Sized> NonNull<T> { | |
83 | /// Creates a new `NonNull`. | |
84 | /// | |
85 | /// # Safety | |
86 | /// | |
87 | /// `ptr` must be non-null. | |
88 | #[stable(feature = "nonnull", since = "1.25.0")] | |
89 | #[cfg_attr( | |
90 | not(bootstrap), | |
91 | rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.32.0"), | |
92 | )] | |
93 | #[inline] | |
94 | pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { | |
95 | NonNull { pointer: ptr as _ } | |
96 | } | |
97 | ||
98 | /// Creates a new `NonNull` if `ptr` is non-null. | |
99 | #[stable(feature = "nonnull", since = "1.25.0")] | |
100 | #[inline] | |
101 | pub fn new(ptr: *mut T) -> Option<Self> { | |
102 | if !ptr.is_null() { Some(unsafe { Self::new_unchecked(ptr) }) } else { None } | |
103 | } | |
104 | ||
105 | /// Acquires the underlying `*mut` pointer. | |
106 | #[stable(feature = "nonnull", since = "1.25.0")] | |
107 | #[cfg_attr( | |
108 | not(bootstrap), | |
109 | rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0"), | |
110 | )] | |
111 | #[inline] | |
112 | pub const fn as_ptr(self) -> *mut T { | |
113 | self.pointer as *mut T | |
114 | } | |
115 | ||
116 | /// Dereferences the content. | |
117 | /// | |
118 | /// The resulting lifetime is bound to self so this behaves "as if" | |
119 | /// it were actually an instance of T that is getting borrowed. If a longer | |
120 | /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. | |
121 | #[stable(feature = "nonnull", since = "1.25.0")] | |
122 | #[inline] | |
123 | pub unsafe fn as_ref(&self) -> &T { | |
124 | &*self.as_ptr() | |
125 | } | |
126 | ||
127 | /// Mutably dereferences the content. | |
128 | /// | |
129 | /// The resulting lifetime is bound to self so this behaves "as if" | |
130 | /// it were actually an instance of T that is getting borrowed. If a longer | |
131 | /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. | |
132 | #[stable(feature = "nonnull", since = "1.25.0")] | |
133 | #[inline] | |
134 | pub unsafe fn as_mut(&mut self) -> &mut T { | |
135 | &mut *self.as_ptr() | |
136 | } | |
137 | ||
138 | /// Casts to a pointer of another type. | |
139 | #[stable(feature = "nonnull_cast", since = "1.27.0")] | |
140 | #[cfg_attr( | |
141 | not(bootstrap), | |
142 | rustc_const_stable(feature = "const_nonnull_cast", since = "1.32.0"), | |
143 | )] | |
144 | #[inline] | |
145 | pub const fn cast<U>(self) -> NonNull<U> { | |
146 | unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } | |
147 | } | |
148 | } | |
149 | ||
150 | #[stable(feature = "nonnull", since = "1.25.0")] | |
151 | impl<T: ?Sized> Clone for NonNull<T> { | |
152 | #[inline] | |
153 | fn clone(&self) -> Self { | |
154 | *self | |
155 | } | |
156 | } | |
157 | ||
158 | #[stable(feature = "nonnull", since = "1.25.0")] | |
159 | impl<T: ?Sized> Copy for NonNull<T> {} | |
160 | ||
161 | #[unstable(feature = "coerce_unsized", issue = "27732")] | |
162 | impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {} | |
163 | ||
164 | #[unstable(feature = "dispatch_from_dyn", issue = "0")] | |
165 | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {} | |
166 | ||
167 | #[stable(feature = "nonnull", since = "1.25.0")] | |
168 | impl<T: ?Sized> fmt::Debug for NonNull<T> { | |
169 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
170 | fmt::Pointer::fmt(&self.as_ptr(), f) | |
171 | } | |
172 | } | |
173 | ||
174 | #[stable(feature = "nonnull", since = "1.25.0")] | |
175 | impl<T: ?Sized> fmt::Pointer for NonNull<T> { | |
176 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
177 | fmt::Pointer::fmt(&self.as_ptr(), f) | |
178 | } | |
179 | } | |
180 | ||
181 | #[stable(feature = "nonnull", since = "1.25.0")] | |
182 | impl<T: ?Sized> Eq for NonNull<T> {} | |
183 | ||
184 | #[stable(feature = "nonnull", since = "1.25.0")] | |
185 | impl<T: ?Sized> PartialEq for NonNull<T> { | |
186 | #[inline] | |
187 | fn eq(&self, other: &Self) -> bool { | |
188 | self.as_ptr() == other.as_ptr() | |
189 | } | |
190 | } | |
191 | ||
192 | #[stable(feature = "nonnull", since = "1.25.0")] | |
193 | impl<T: ?Sized> Ord for NonNull<T> { | |
194 | #[inline] | |
195 | fn cmp(&self, other: &Self) -> Ordering { | |
196 | self.as_ptr().cmp(&other.as_ptr()) | |
197 | } | |
198 | } | |
199 | ||
200 | #[stable(feature = "nonnull", since = "1.25.0")] | |
201 | impl<T: ?Sized> PartialOrd for NonNull<T> { | |
202 | #[inline] | |
203 | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | |
204 | self.as_ptr().partial_cmp(&other.as_ptr()) | |
205 | } | |
206 | } | |
207 | ||
208 | #[stable(feature = "nonnull", since = "1.25.0")] | |
209 | impl<T: ?Sized> hash::Hash for NonNull<T> { | |
210 | #[inline] | |
211 | fn hash<H: hash::Hasher>(&self, state: &mut H) { | |
212 | self.as_ptr().hash(state) | |
213 | } | |
214 | } | |
215 | ||
216 | #[unstable(feature = "ptr_internals", issue = "0")] | |
217 | impl<T: ?Sized> From<Unique<T>> for NonNull<T> { | |
218 | #[inline] | |
219 | fn from(unique: Unique<T>) -> Self { | |
220 | unsafe { NonNull::new_unchecked(unique.as_ptr()) } | |
221 | } | |
222 | } | |
223 | ||
224 | #[stable(feature = "nonnull", since = "1.25.0")] | |
225 | impl<T: ?Sized> From<&mut T> for NonNull<T> { | |
226 | #[inline] | |
227 | fn from(reference: &mut T) -> Self { | |
228 | unsafe { NonNull { pointer: reference as *mut T } } | |
229 | } | |
230 | } | |
231 | ||
232 | #[stable(feature = "nonnull", since = "1.25.0")] | |
233 | impl<T: ?Sized> From<&T> for NonNull<T> { | |
234 | #[inline] | |
235 | fn from(reference: &T) -> Self { | |
236 | unsafe { NonNull { pointer: reference as *const T } } | |
237 | } | |
238 | } |