rust: retain pointer mut-ness in container_of!

Avoid casting the input pointer to `*const _`, allowing the output
pointer to be `*mut` if the input is `*mut`. This allows a number of
`*const` to `*mut` conversions to be removed at the cost of slightly
worse ergonomics when the macro is used with a reference rather than a
pointer; the only example of this was in the macro's own doctest.

Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Tamir Duberstein <tamird@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250409-container-of-mutness-v1-1-64f472b94534@gmail.com
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Tamir Duberstein 2025-04-09 10:43:16 -04:00 committed by Miguel Ojeda
parent a3b2347343
commit 74d6a606c2
2 changed files with 12 additions and 16 deletions

View file

@ -205,7 +205,7 @@ fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
/// } /// }
/// ///
/// let test = Test { a: 10, b: 20 }; /// let test = Test { a: 10, b: 20 };
/// let b_ptr = &test.b; /// let b_ptr: *const _ = &test.b;
/// // SAFETY: The pointer points at the `b` field of a `Test`, so the resulting pointer will be /// // SAFETY: The pointer points at the `b` field of a `Test`, so the resulting pointer will be
/// // in-bounds of the same allocation as `b_ptr`. /// // in-bounds of the same allocation as `b_ptr`.
/// let test_alias = unsafe { container_of!(b_ptr, Test, b) }; /// let test_alias = unsafe { container_of!(b_ptr, Test, b) };
@ -214,9 +214,8 @@ fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
#[macro_export] #[macro_export]
macro_rules! container_of { macro_rules! container_of {
($ptr:expr, $type:ty, $($f:tt)*) => {{ ($ptr:expr, $type:ty, $($f:tt)*) => {{
let ptr = $ptr as *const _ as *const u8;
let offset: usize = ::core::mem::offset_of!($type, $($f)*); let offset: usize = ::core::mem::offset_of!($type, $($f)*);
ptr.sub(offset) as *const $type $ptr.byte_sub(offset).cast::<$type>()
}} }}
} }

View file

@ -424,7 +424,7 @@ where
while !node.is_null() { while !node.is_null() {
// SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self` // SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self`
// point to the links field of `Node<K, V>` objects. // point to the links field of `Node<K, V>` objects.
let this = unsafe { container_of!(node, Node<K, V>, links) }.cast_mut(); let this = unsafe { container_of!(node, Node<K, V>, links) };
// SAFETY: `this` is a non-null node so it is valid by the type invariants. // SAFETY: `this` is a non-null node so it is valid by the type invariants.
let this_key = unsafe { &(*this).key }; let this_key = unsafe { &(*this).key };
// SAFETY: `node` is a non-null node so it is valid by the type invariants. // SAFETY: `node` is a non-null node so it is valid by the type invariants.
@ -496,7 +496,7 @@ impl<K, V> Drop for RBTree<K, V> {
// but it is not observable. The loop invariant is still maintained. // but it is not observable. The loop invariant is still maintained.
// SAFETY: `this` is valid per the loop invariant. // SAFETY: `this` is valid per the loop invariant.
unsafe { drop(KBox::from_raw(this.cast_mut())) }; unsafe { drop(KBox::from_raw(this)) };
} }
} }
} }
@ -761,7 +761,7 @@ impl<'a, K, V> Cursor<'a, K, V> {
let next = self.get_neighbor_raw(Direction::Next); let next = self.get_neighbor_raw(Direction::Next);
// SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self` // SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self`
// point to the links field of `Node<K, V>` objects. // point to the links field of `Node<K, V>` objects.
let this = unsafe { container_of!(self.current.as_ptr(), Node<K, V>, links) }.cast_mut(); let this = unsafe { container_of!(self.current.as_ptr(), Node<K, V>, links) };
// SAFETY: `this` is valid by the type invariants as described above. // SAFETY: `this` is valid by the type invariants as described above.
let node = unsafe { KBox::from_raw(this) }; let node = unsafe { KBox::from_raw(this) };
let node = RBTreeNode { node }; let node = RBTreeNode { node };
@ -806,7 +806,7 @@ impl<'a, K, V> Cursor<'a, K, V> {
unsafe { bindings::rb_erase(neighbor, addr_of_mut!(self.tree.root)) }; unsafe { bindings::rb_erase(neighbor, addr_of_mut!(self.tree.root)) };
// SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self` // SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self`
// point to the links field of `Node<K, V>` objects. // point to the links field of `Node<K, V>` objects.
let this = unsafe { container_of!(neighbor, Node<K, V>, links) }.cast_mut(); let this = unsafe { container_of!(neighbor, Node<K, V>, links) };
// SAFETY: `this` is valid by the type invariants as described above. // SAFETY: `this` is valid by the type invariants as described above.
let node = unsafe { KBox::from_raw(this) }; let node = unsafe { KBox::from_raw(this) };
return Some(RBTreeNode { node }); return Some(RBTreeNode { node });
@ -912,7 +912,7 @@ impl<'a, K, V> Cursor<'a, K, V> {
unsafe fn to_key_value_raw<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, *mut V) { unsafe fn to_key_value_raw<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, *mut V) {
// SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self` // SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self`
// point to the links field of `Node<K, V>` objects. // point to the links field of `Node<K, V>` objects.
let this = unsafe { container_of!(node.as_ptr(), Node<K, V>, links) }.cast_mut(); let this = unsafe { container_of!(node.as_ptr(), Node<K, V>, links) };
// SAFETY: The passed `node` is the current node or a non-null neighbor, // SAFETY: The passed `node` is the current node or a non-null neighbor,
// thus `this` is valid by the type invariants. // thus `this` is valid by the type invariants.
let k = unsafe { &(*this).key }; let k = unsafe { &(*this).key };
@ -1021,7 +1021,7 @@ impl<K, V> Iterator for IterRaw<K, V> {
// SAFETY: By the type invariant of `IterRaw`, `self.next` is a valid node in an `RBTree`, // SAFETY: By the type invariant of `IterRaw`, `self.next` is a valid node in an `RBTree`,
// and by the type invariant of `RBTree`, all nodes point to the links field of `Node<K, V>` objects. // and by the type invariant of `RBTree`, all nodes point to the links field of `Node<K, V>` objects.
let cur = unsafe { container_of!(self.next, Node<K, V>, links) }.cast_mut(); let cur = unsafe { container_of!(self.next, Node<K, V>, links) };
// SAFETY: `self.next` is a valid tree node by the type invariants. // SAFETY: `self.next` is a valid tree node by the type invariants.
self.next = unsafe { bindings::rb_next(self.next) }; self.next = unsafe { bindings::rb_next(self.next) };
@ -1216,7 +1216,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
// SAFETY: // SAFETY:
// - `self.node_links` is a valid pointer to a node in the tree. // - `self.node_links` is a valid pointer to a node in the tree.
// - We have exclusive access to the underlying tree, and can thus give out a mutable reference. // - We have exclusive access to the underlying tree, and can thus give out a mutable reference.
unsafe { &mut (*(container_of!(self.node_links, Node<K, V>, links).cast_mut())).value } unsafe { &mut (*(container_of!(self.node_links, Node<K, V>, links))).value }
} }
/// Converts the entry into a mutable reference to its value. /// Converts the entry into a mutable reference to its value.
@ -1226,7 +1226,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
// SAFETY: // SAFETY:
// - `self.node_links` is a valid pointer to a node in the tree. // - `self.node_links` is a valid pointer to a node in the tree.
// - This consumes the `&'a mut RBTree<K, V>`, therefore it can give out a mutable reference that lives for `'a`. // - This consumes the `&'a mut RBTree<K, V>`, therefore it can give out a mutable reference that lives for `'a`.
unsafe { &mut (*(container_of!(self.node_links, Node<K, V>, links).cast_mut())).value } unsafe { &mut (*(container_of!(self.node_links, Node<K, V>, links))).value }
} }
/// Remove this entry from the [`RBTree`]. /// Remove this entry from the [`RBTree`].
@ -1239,9 +1239,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
RBTreeNode { RBTreeNode {
// SAFETY: The node was a node in the tree, but we removed it, so we can convert it // SAFETY: The node was a node in the tree, but we removed it, so we can convert it
// back into a box. // back into a box.
node: unsafe { node: unsafe { KBox::from_raw(container_of!(self.node_links, Node<K, V>, links)) },
KBox::from_raw(container_of!(self.node_links, Node<K, V>, links).cast_mut())
},
} }
} }
@ -1272,8 +1270,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
// SAFETY: // SAFETY:
// - `self.node_ptr` produces a valid pointer to a node in the tree. // - `self.node_ptr` produces a valid pointer to a node in the tree.
// - Now that we removed this entry from the tree, we can convert the node to a box. // - Now that we removed this entry from the tree, we can convert the node to a box.
let old_node = let old_node = unsafe { KBox::from_raw(container_of!(self.node_links, Node<K, V>, links)) };
unsafe { KBox::from_raw(container_of!(self.node_links, Node<K, V>, links).cast_mut()) };
RBTreeNode { node: old_node } RBTreeNode { node: old_node }
} }