Skip to main content

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> {}