From mboxrd@z Thu Jan 1 00:00:00 1970 From: Claude Code Review Bot To: dri-devel-reviews@example.com Subject: Claude review: rust: clist: Add support to interface with C linked lists Date: Fri, 13 Feb 2026 06:27:35 +1000 Message-ID: In-Reply-To: <20260210233204.790524-2-joelagnelf@nvidia.com> References: <20260210233204.790524-1-joelagnelf@nvidia.com> <20260210233204.790524-2-joelagnelf@nvidia.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Mailer: Claude Code Patch Reviewer Patch Review > + pub fn is_linked(&self) -> bool { > + let raw = self.as_raw(); > + // SAFETY: self.as_raw() is valid per type invariants. > + unsafe { (*raw).next != raw && (*raw).prev != raw } > + } The kernel's `list_empty()` checks `head->next == head`. An isolated/empty node has both `next` and `prev` pointing to itself after `INIT_LIST_HEAD`. Using `&&` here means a node where only `next` has been corrupted to point elsewhere (but `prev` still points to self) would be considered "linked." This seems unlikely in practice, but it might be worth noting that the kernel's own `list_empty` only checks `next`. For the actual use in this series (`is_empty` on `CList` returns `!is_linked()`), the behavior is functionally equivalent for properly-formed lists, so this is a minor observation. > + pub fn next(&self) -> &Self { > + let raw = self.as_raw(); > + // SAFETY: > + // - `self.as_raw()` is valid per type invariants. > + // - The `next` pointer is guaranteed to be non-NULL. > + unsafe { Self::from_raw((*raw).next) } > + } The `next()` method returns `&Self` with the same lifetime as the `from_raw` call. Since `from_raw` binds the lifetime to the caller's choice via `'a`, and `next()` borrows `&self`, the returned reference is correctly constrained to the lifetime of `self`. No issue here. > +macro_rules! clist_create { > + ($head:expr, $rust_type:ty, $c_type:ty, $($field:tt).+) => {{ > + // Compile-time check that field path is a list_head. > + let _: fn(*const $c_type) -> *const $crate::bindings::list_head = > + |p| &raw const (*p).$($field).+; > + > + // Calculate offset and create `CList`. > + const OFFSET: usize = ::core::mem::offset_of!($c_type, $($field).+); > + $crate::clist::CList::<$rust_type, OFFSET>::from_raw($head) > + }}; > +} The macro calls `CList::from_raw($head)` which is an `unsafe` function, but the macro itself is documented as unsafe. The compile-time field type check is a nice touch. However, the type-checking closure `let _: fn(...) -> ...` constructs a function value that is never used - it could arguably be a `const _` or similar, but as-is it works for compile-time verification. The `CListHeadIter` implements `FusedIterator`, which is correct since after returning `None` (when `current == sentinel`), it will continue to return `None` - `current` is never advanced past the sentinel. No significant issues found. This is a clean implementation of a read-only C list iteration interface. --- Generated by Claude Code Patch Reviewer