abi_stable/sabi_types/rref.rs
1use std::{
2 fmt::{self, Display},
3 marker::PhantomData,
4 ptr::NonNull,
5};
6
7use crate::{
8 pointer_trait::{AsPtr, CanTransmuteElement, GetPointerKind, PK_Reference},
9 utils::ref_as_nonnull,
10};
11
12/// Equivalent to `&'a T`,
13/// which allows a few more operations without causing Undefined Behavior.
14///
15/// # Purpose
16///
17/// This type is used as the `&self` parameter in abi_stable trait objects
18/// because it can be soundly transmuted
19/// to point to other smaller but compatible types, then back to the original type.
20///
21/// This crate is tested with [miri] to detect bugs in unsafe code,
22/// which implements the [Stacked Borrows model].
23/// Because that model forbids `&T` to `&()` to `&T` transmutes (when `T` isn't zero-sized),
24/// it required defining `RRef` to allow a reference-like type that can be transmuted.
25///
26/// # Example
27///
28/// This example demonstrates how a simple `&dyn Any`-like type can be implemented.
29///
30/// ```rust
31/// use abi_stable::{marker_type::ErasedObject, std_types::UTypeId, RRef};
32///
33/// fn main() {
34/// let value = WithTypeId::new(5u32);
35/// let erased = value.erase();
36///
37/// assert_eq!(WithTypeId::downcast::<i32>(erased), None);
38/// assert_eq!(WithTypeId::downcast::<bool>(erased), None);
39/// assert_eq!(WithTypeId::downcast::<u32>(erased), Some(&value));
40/// }
41///
42/// // `#[repr(C))]` with a trailing `T` field is required for soundly transmuting from
43/// // `RRef<'a, WithTypeId<T>>` to `RRef<'a, WithTypeId<ErasedObject>>`.
44/// #[repr(C)]
45/// #[derive(Debug, PartialEq)]
46/// struct WithTypeId<T> {
47/// type_id: UTypeId,
48/// value: T,
49/// }
50///
51/// impl<T> WithTypeId<T> {
52/// pub fn new(value: T) -> Self
53/// where
54/// T: 'static,
55/// {
56/// Self {
57/// type_id: UTypeId::new::<T>(),
58/// value,
59/// }
60/// }
61///
62/// pub fn erase(&self) -> RRef<'_, WithTypeId<ErasedObject>> {
63/// unsafe { RRef::new(self).transmute::<WithTypeId<ErasedObject>>() }
64/// }
65/// }
66///
67/// impl WithTypeId<ErasedObject> {
68/// pub fn downcast<T>(this: RRef<'_, Self>) -> Option<&WithTypeId<T>>
69/// where
70/// T: 'static,
71/// {
72/// if this.get().type_id == UTypeId::new::<T>() {
73/// // safety: we checked that type parameter was `T`
74/// unsafe { Some(this.transmute_into_ref::<WithTypeId<T>>()) }
75/// } else {
76/// None
77/// }
78/// }
79/// }
80///
81///
82/// ```
83///
84/// <span id="type-prefix-exp"></span>
85/// # Type Prefix
86///
87/// A type parameter `U` is considered a prefix of `T` in all of these cases:
88///
89/// - `U` is a zero-sized type with an alignment equal or lower than `T`
90///
91/// - `U` is a `#[repr(transparent)]` wrapper over `T`
92///
93/// - `U` and `T` are both `#[repr(C)]` structs,
94/// in which `T` starts with the fields of `U` in the same order,
95/// and `U` has an alignment equal to or lower than `T`.
96///
97/// Please note that it can be unsound to transmute a non-local
98/// type if it has private fields,
99/// since it may assume it was constructed in a particular way.
100///
101/// [Stacked Borrows model]:
102/// https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md
103///
104/// [miri]: https://github.com/rust-lang/miri
105///
106#[repr(transparent)]
107#[derive(StableAbi)]
108#[sabi(bound(T:'a))]
109pub struct RRef<'a, T> {
110 ref_: NonNull<T>,
111 _marker: PhantomData<&'a T>,
112}
113
114impl<'a, T> Display for RRef<'a, T>
115where
116 T: Display,
117{
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 Display::fmt(self.get(), f)
120 }
121}
122
123impl<'a, T> Clone for RRef<'a, T> {
124 fn clone(&self) -> Self {
125 *self
126 }
127}
128
129impl<'a, T> Copy for RRef<'a, T> {}
130
131unsafe impl<'a, T> Sync for RRef<'a, T> where &'a T: Sync {}
132
133unsafe impl<'a, T> Send for RRef<'a, T> where &'a T: Send {}
134
135shared_impls! {
136 mod=static_ref_impls
137 new_type=RRef['a][T],
138 original_type=AAAA,
139 deref_approach=(method = get),
140}
141
142impl<'a, T> RRef<'a, T> {
143 /// Constructs this RRef from a reference.
144 ///
145 /// # Example
146 ///
147 /// ```
148 /// use abi_stable::sabi_types::RRef;
149 ///
150 /// struct GetPtr<'a, T>(&'a T);
151 ///
152 /// impl<'a, T: 'a> GetPtr<'a, T> {
153 /// const REF: &'a Option<T> = &None;
154 ///
155 /// const STATIC: RRef<'a, Option<T>> = RRef::new(Self::REF);
156 /// }
157 ///
158 /// ```
159 #[inline(always)]
160 pub const fn new(ref_: &'a T) -> Self {
161 Self {
162 ref_: ref_as_nonnull(ref_),
163 _marker: PhantomData,
164 }
165 }
166
167 /// Constructs this RRef from a raw pointer.
168 ///
169 /// # Safety
170 ///
171 /// You must ensure that the raw pointer is valid for the `'a` lifetime,
172 /// and points to a fully initialized and aligned `T`.
173 ///
174 /// # Example
175 ///
176 /// ```
177 /// use abi_stable::sabi_types::RRef;
178 ///
179 /// struct GetPtr<'a, T>(&'a T);
180 ///
181 /// impl<'a, T: 'a> GetPtr<'a, T> {
182 /// const PTR: *const Option<T> = &None;
183 ///
184 /// const STATIC: RRef<'a, Option<T>> = unsafe { RRef::from_raw(Self::PTR) };
185 /// }
186 ///
187 /// ```
188 #[inline(always)]
189 pub const unsafe fn from_raw(ref_: *const T) -> Self
190 where
191 T: 'a,
192 {
193 Self {
194 ref_: unsafe { NonNull::new_unchecked(ref_ as *mut T) },
195 _marker: PhantomData,
196 }
197 }
198
199 /// Casts this to an equivalent reference.
200 ///
201 /// # Example
202 ///
203 /// ```rust
204 /// use abi_stable::RRef;
205 ///
206 /// let rref = RRef::new(&89);
207 ///
208 /// assert_eq!(rref.get(), &89);
209 ///
210 /// ```
211 #[inline(always)]
212 pub const fn get(self) -> &'a T {
213 unsafe { crate::utils::deref!(self.ref_.as_ptr()) }
214 }
215
216 /// Copies the value that this points to.
217 ///
218 /// # Example
219 ///
220 /// ```rust
221 /// use abi_stable::RRef;
222 ///
223 /// let rref = RRef::new(&55);
224 ///
225 /// assert_eq!(rref.get_copy(), 55);
226 ///
227 /// ```
228 #[inline(always)]
229 pub const fn get_copy(self) -> T
230 where
231 T: Copy,
232 {
233 unsafe { *(self.ref_.as_ptr() as *const T) }
234 }
235
236 /// Casts this to an equivalent raw pointer.
237 ///
238 /// # Example
239 ///
240 /// ```rust
241 /// use abi_stable::RRef;
242 ///
243 /// let rref = RRef::new(&89);
244 ///
245 /// unsafe {
246 /// assert_eq!(*rref.as_ptr(), 89);
247 /// }
248 /// ```
249 #[inline(always)]
250 pub const fn as_ptr(self) -> *const T {
251 self.ref_.as_ptr() as *const T
252 }
253
254 /// Transmutes this `RRef<'a,T>` to a `RRef<'a,U>`.
255 ///
256 /// # Safety
257 ///
258 /// Either of these must be the case:
259 ///
260 /// - [`U` is a prefix of `T`](#type-prefix-exp)
261 ///
262 /// - `RRef<'a, U>` was the original type of this `RRef<'a, T>`.
263 ///
264 /// # Example
265 ///
266 /// ```
267 /// use abi_stable::RRef;
268 ///
269 /// use std::num::Wrapping;
270 ///
271 /// let rref = RRef::new(&13u32);
272 ///
273 /// // safety: Wrapping is a `#[repr(transparent)]` wrapper with one `pub` field.
274 /// let trans = unsafe { rref.transmute::<Wrapping<u32>>() };
275 ///
276 /// assert_eq!(trans, RRef::new(&Wrapping(13u32)));
277 ///
278 ///
279 /// ```
280 #[inline(always)]
281 pub const unsafe fn transmute<U>(self) -> RRef<'a, U>
282 where
283 U: 'a,
284 {
285 unsafe { RRef::from_raw(self.ref_.as_ptr() as *const U) }
286 }
287
288 /// Transmutes this to a raw pointer pointing to a different type.
289 #[inline(always)]
290 pub const fn transmute_into_raw<U>(self) -> *const U {
291 self.ref_.as_ptr() as *const T as *const U
292 }
293
294 /// Transmutes this to a reference pointing to a different type.
295 ///
296 /// # Safety
297 ///
298 /// Either of these must be the case:
299 ///
300 /// - [`U` is a prefix of `T`](#type-prefix-exp)
301 ///
302 /// - `RRef<'a, U>` was the original type of this `RRef<'a, T>`.
303 ///
304 /// # Example
305 ///
306 /// ```rust
307 /// use abi_stable::{std_types::Tuple2, RRef};
308 ///
309 /// unsafe {
310 /// let reff = RRef::new(&Tuple2(3u32, 5u64));
311 /// assert_eq!(reff.transmute_into_ref::<u32>(), &3u32);
312 /// }
313 ///
314 /// ```
315 #[inline(always)]
316 pub const unsafe fn transmute_into_ref<U>(self) -> &'a U
317 where
318 U: 'a,
319 {
320 unsafe { crate::utils::deref!(self.ref_.as_ptr() as *const T as *const U) }
321 }
322}
323
324unsafe impl<'a, T> GetPointerKind for RRef<'a, T> {
325 type Kind = PK_Reference;
326
327 type PtrTarget = T;
328}
329
330unsafe impl<'a, T, U> CanTransmuteElement<U> for RRef<'a, T>
331where
332 U: 'a,
333{
334 type TransmutedPtr = RRef<'a, U>;
335
336 #[inline(always)]
337 unsafe fn transmute_element_(self) -> Self::TransmutedPtr {
338 unsafe { self.transmute() }
339 }
340}
341
342unsafe impl<T> AsPtr for RRef<'_, T> {
343 #[inline(always)]
344 fn as_ptr(&self) -> *const T {
345 self.ref_.as_ptr() as *const T
346 }
347
348 #[inline(always)]
349 fn as_rref(&self) -> RRef<'_, T> {
350 *self
351 }
352}
353
354#[cfg(test)]
355mod tests {
356 use super::*;
357
358 #[test]
359 fn construction_test() {
360 unsafe {
361 let three: *const i32 = &3;
362 assert_eq!(RRef::from_raw(three).get_copy(), 3);
363 }
364
365 assert_eq!(RRef::new(&5).get_copy(), 5);
366 }
367
368 #[test]
369 fn access() {
370 let reference = RRef::new(&8);
371
372 assert_eq!(*reference.get(), 8);
373 assert_eq!(reference.get_copy(), 8);
374 unsafe {
375 assert_eq!(*reference.as_ptr(), 8);
376 }
377 }
378
379 #[test]
380 fn transmutes() {
381 let reference = RRef::new(&(!0u32));
382
383 unsafe {
384 assert_eq!(reference.transmute::<i32>().get_copy(), -1);
385 assert_eq!(*reference.transmute_into_raw::<i32>(), -1);
386 assert_eq!(reference.transmute_into_ref::<i32>(), &-1);
387 }
388 }
389
390 #[test]
391 fn as_ptr_impl() {
392 let reference = RRef::new(&89u32);
393
394 unsafe {
395 assert_eq!(*AsPtr::as_ptr(&reference), 89);
396 assert_eq!(AsPtr::as_rref(&reference), reference);
397 }
398 }
399}