fbl/ptr_traits.rs
1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::recyclable::Recyclable;
6use crate::ref_counted::HasRefCount;
7use crate::ref_ptr::RefPtr;
8use crate::unique_ptr::UniquePtr;
9use core::ops::Deref;
10use core::ptr::NonNull;
11
12/// Trait for pointer types that can be stored in intrusive containers.
13///
14/// # Safety
15///
16/// Implementing this trait is unsafe because the container relies on the correctness of
17/// the implementation to maintain memory safety:
18/// - `into_raw` must return a valid, non-null, and dereferenceable pointer to `Target` that
19/// uniquely identifies the object.
20/// - `from_raw` must correctly reconstruct a valid instance of `Self` from a pointer previously
21/// returned by `into_raw`.
22/// - `from_raw` must reclaim the ownership previously yielded by `into_raw`.
23/// - `get_ref` must return a valid reference to the `Target`.
24pub unsafe trait PtrTraits {
25 /// The type pointed to by this pointer.
26 type Target;
27 /// Whether the pointer type is managed (e.g., `UniquePtr` or `RefPtr`).
28 ///
29 /// If the pointer type is managed, containers can be dropped while they
30 /// are non-empty because the pointers can free the underlying memory. If
31 /// the pointer is not managed, then the containers need to be empty when
32 /// they are dropped to avoid memory leaks.
33 const IS_MANAGED: bool;
34 /// Consumes the pointer and returns a raw pointer to the target.
35 fn into_raw(self) -> *mut Self::Target;
36 /// Creates an instance of `Self` from a raw pointer.
37 ///
38 /// # Safety
39 ///
40 /// The caller must ensure that `raw` was returned by a previous call to
41 /// `into_raw` on an instance of `Self`, and that it has not been used to
42 /// create another instance of `Self`.
43 unsafe fn from_raw(raw: *mut Self::Target) -> Self;
44 /// Returns a reference to the target.
45 fn get_ref(&self) -> &Self::Target;
46}
47
48// SAFETY: `*mut T` behaves as a raw pointer with identity mapped into/from raw conversions.
49// It performs no lifecycle management and get_ref is safe if the pointer is valid.
50unsafe impl<T> PtrTraits for *mut T {
51 type Target = T;
52 const IS_MANAGED: bool = false;
53 #[inline]
54 fn into_raw(self) -> *mut T {
55 self
56 }
57 #[inline]
58 unsafe fn from_raw(raw: *mut T) -> Self {
59 raw
60 }
61 #[inline]
62 fn get_ref(&self) -> &T {
63 // SAFETY: The caller must ensure that `self` (which is `&(*mut T)`) points to a valid T.
64 unsafe { &**self }
65 }
66}
67
68// SAFETY: `NonNull<T>` behaves as a raw pointer with identity mapped into/from raw conversions.
69// It performs no lifecycle management and get_ref is safe if the pointer is valid.
70unsafe impl<T> PtrTraits for NonNull<T> {
71 type Target = T;
72 const IS_MANAGED: bool = false;
73 #[inline]
74 fn into_raw(self) -> *mut T {
75 self.as_ptr()
76 }
77 #[inline]
78 unsafe fn from_raw(raw: *mut T) -> Self {
79 // SAFETY: The caller of `from_raw` must ensure that `raw` was returned
80 // by a previous call to `into_raw` on an instance of `Self`. Since `into_raw`
81 // for `NonNull` always returns a non-null pointer, `raw` is guaranteed to be non-null.
82 unsafe { NonNull::new_unchecked(raw) }
83 }
84 #[inline]
85 fn get_ref(&self) -> &T {
86 // SAFETY: The caller must ensure that `self` points to a valid T.
87 unsafe { self.as_ref() }
88 }
89}
90
91// SAFETY: `UniquePtr<T>` owns the unique reference to `T`. Roundtrip between into_raw
92// and from_raw is guaranteed to preserve unique ownership and lifetimes.
93unsafe impl<T: Recyclable> PtrTraits for UniquePtr<T> {
94 type Target = T;
95 const IS_MANAGED: bool = true;
96 #[inline]
97 fn into_raw(self) -> *mut T {
98 UniquePtr::into_raw(self)
99 }
100 #[inline]
101 unsafe fn from_raw(raw: *mut T) -> Self {
102 // SAFETY: The caller of `from_raw` must ensure that `raw` was returned
103 // by a previous call to `into_raw` on an instance of `Self`, and that it
104 // has not been used to create another instance of `Self`.
105 unsafe { UniquePtr::from_raw(raw) }
106 }
107 #[inline]
108 fn get_ref(&self) -> &T {
109 self.deref()
110 }
111}
112
113// SAFETY: `RefPtr<T>` manages a shared atomic ref-count on `T`. Roundtrip between
114// into_raw and from_raw correctly transfers a single reference.
115unsafe impl<T: HasRefCount + Recyclable> PtrTraits for RefPtr<T> {
116 type Target = T;
117 const IS_MANAGED: bool = true;
118 #[inline]
119 fn into_raw(self) -> *mut T {
120 RefPtr::into_raw(self) as *mut T
121 }
122 #[inline]
123 unsafe fn from_raw(raw: *mut T) -> Self {
124 // SAFETY: The caller of `from_raw` must ensure that `raw` was returned
125 // by a previous call to `into_raw` on an instance of `Self`, and that it
126 // has not been used to create another instance of `Self`.
127 unsafe { RefPtr::from_raw(raw) }
128 }
129 #[inline]
130 fn get_ref(&self) -> &T {
131 self.deref()
132 }
133}
134
135/// Marker trait for managed pointer types (like `UniquePtr` and `RefPtr`).
136///
137/// # Safety
138///
139/// Implementing this trait is unsafe because:
140/// - The implementer must guarantee that the pointer type `P` actually manages the lifetime
141/// of its `Target` (i.e., it holds exclusive or shared ownership of the target).
142/// - Dropping the pointer `P` must correctly release the reference/ownership, causing the
143/// target to be dropped and cleaned up once there are no more owners.
144/// - The target object must be guaranteed to outlive its reference in the list while contained.
145pub unsafe trait ManagedPtr: PtrTraits {}
146
147// SAFETY: `UniquePtr<T>` uniquely manages `T`'s lifetime.
148unsafe impl<T: Recyclable> ManagedPtr for UniquePtr<T> {}
149// SAFETY: `RefPtr<T>` manages `T`'s lifetime via atomic reference counting.
150unsafe impl<T: HasRefCount + Recyclable> ManagedPtr for RefPtr<T> {}
151
152/// Marker trait for pointer types through which intrusive containers may hand out mutable
153/// (pinned) access to their elements (e.g. `front_mut()`, `iter_mut()`, `CursorMut::get_mut()`).
154///
155/// # Safety
156///
157/// Implementing this trait is unsafe because containers rely on it to soundly produce
158/// `Pin<&mut Self::Target>` from their stored pointers. The implementer must guarantee that
159/// exclusive access to a container holding `Self` (i.e. `Pin<&mut Container<Self>>`) implies
160/// exclusive mutable access to every `Self::Target` stored in it. In particular:
161/// - `Self` must not represent shared ownership of the target (as `RefPtr<T>` does), since other
162/// owners could otherwise observe the target while it is being mutated through the container.
163/// - For unmanaged pointers (e.g. `*mut T`, `NonNull<T>`), when mutable element accessors
164/// (`front_mut`, `back_mut`, `iter_mut`, `CursorMut::get_mut`, etc.) are used on the container,
165/// callers of the container's `unsafe` raw insertion APIs take on the obligation that no other
166/// references to the element are accessed while it is mutably borrowed through the container.
167/// - Because mutable element accessors expose `Pin<&mut Self::Target>`, elements accessed through
168/// them must satisfy `Pin`'s drop guarantee: unless `Self::Target: Unpin`, an element must not be
169/// moved out of its memory location (or have that memory reused) before it is dropped. For
170/// managed pointers this is upheld by the pointer type itself; for unmanaged pointers it is an
171/// obligation of the callers of the container's `unsafe` raw insertion APIs.
172pub unsafe trait MutPtr: PtrTraits {}
173
174// SAFETY: Raw pointers carry no ownership. When mutable element accessors are used, callers of the
175// `unsafe` raw insertion APIs guarantee that no other references to the pointee are accessed while
176// it is mutably borrowed through the container, and that the pointee satisfies `Pin`'s drop
177// guarantee (it is not moved before being dropped).
178unsafe impl<T> MutPtr for *mut T {}
179// SAFETY: `NonNull<T>` carries no ownership. When mutable element accessors are used, callers of
180// the `unsafe` raw insertion APIs guarantee that no other references to the pointee are accessed
181// while it is mutably borrowed through the container, and that the pointee satisfies `Pin`'s drop
182// guarantee (it is not moved before being dropped).
183unsafe impl<T> MutPtr for NonNull<T> {}
184// SAFETY: `UniquePtr<T>` holds the only reference to `T`, so exclusive access to the container
185// that owns it implies exclusive access to `T`.
186unsafe impl<T: Recyclable> MutPtr for UniquePtr<T> {}