mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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:
		
							parent
							
								
									a3b2347343
								
							
						
					
					
						commit
						74d6a606c2
					
				
					 2 changed files with 12 additions and 16 deletions
				
			
		| 
						 | 
					@ -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>()
 | 
				
			||||||
    }}
 | 
					    }}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -424,7 +424,7 @@ pub fn cursor_lower_bound(&mut self, key: &K) -> Option<Cursor<'_, K, V>>
 | 
				
			||||||
        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 @@ fn drop(&mut self) {
 | 
				
			||||||
            // 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 @@ pub fn remove_current(self) -> (Option<Self>, RBTreeNode<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 @@ fn remove_neighbor(&mut self, direction: Direction) -> Option<RBTreeNode<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 @@ unsafe fn to_key_value_mut<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, &'b
 | 
				
			||||||
    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 @@ fn next(&mut self) -> Option<Self::Item> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 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 @@ pub fn get_mut(&mut self) -> &mut 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 @@ pub fn into_mut(self) -> &'a mut 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 @@ pub fn remove_node(self) -> RBTreeNode<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 @@ fn replace(self, node: RBTreeNode<K, V>) -> RBTreeNode<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 }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue