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: devres: return reference in `devres::register` Date: Mon, 16 Mar 2026 12:17:35 +1000 Message-ID: In-Reply-To: <20260313-rust_serdev-v3-1-c9a3af214f7f@posteo.de> References: <20260313-rust_serdev-v3-0-c9a3af214f7f@posteo.de> <20260313-rust_serdev-v3-1-c9a3af214f7f@posteo.de> X-Mailer: Claude Code Patch Reviewer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Patch Review This patch changes `devres::register` to return `Result<&'a T>` instead of `Result`, tying the returned reference's lifetime to the `Device` reference. **Critical safety concern with the lifetime reasoning:** ```rust +pub fn register<'a, T, E>( + dev: &'a Device, + data: impl PinInit, + flags: Flags, +) -> Result<&'a T> ``` The SAFETY comment states: ```rust + // SAFETY: `dev` is valid for the lifetime of 'a. As long as there is a reference to + // `Device`, it is guaranteed that the device is not unbound and data has not been + // dropped. Thus `data_ptr` is also valid for the lifetime of 'a. ``` The issue is that `data` is moved into `register_foreign` via `KBox::pin_init` and then consumed by `into_foreign()` inside `register_foreign`. The raw pointer `data_ptr` is taken *before* the data is registered with devres. If `register_foreign` fails (returns an error), `data` is dropped, but we never reach the `.map()` so that's OK. However, the lifetime argument is subtle: the devres-managed data could in theory be freed by devres callbacks (e.g., if the device is removed concurrently) while a `&'a T` reference is still held. The safety argument relies on `Device` guaranteeing the device won't unbind while the reference exists. This needs careful scrutiny from the Rust-for-Linux maintainers (Danilo, Benno, Alice) to verify the invariant actually holds. **The callers now discard the return value:** ```rust - devres::register(dev, Self::new()?, GFP_KERNEL) + devres::register(dev, Self::new()?, GFP_KERNEL)?; + Ok(()) ``` This works but changes the API for all existing callers to require `?;` + `Ok(())` where they previously just returned the `Result`. This is somewhat unfortunate ergonomically. An alternative approach might be a separate `devres::register_ref` function to avoid forcing this pattern on callers that don't need the reference. --- Generated by Claude Code Patch Reviewer