From 666b3e7cfa3a5c6afbfb2b5dae017617dfc40863 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 23 Sep 2026 19:20:18 +0100 Subject: [PATCH] rust: pin-init: add diagnostic attribute for `PinInit` and `Init` Give a slightly more useful error message when these traits are not implemented. Before this change: error[E0277]: the trait bound `impl pin_init::PinInit: Init` is not satisfied --> tests/ui/compile-fail/init/invalid_init.rs:19:16 | 19 | bar <- Bar::new(), | -------^^^^^^^^^^ | | | | | the trait `Init` is not implemented for `impl pin_init::PinInit` | required by a bound introduced by this call After this change: error[E0277]: `impl pin_init::PinInit` cannot be used to movably initialize `Bar` with error `_` --> tests/ui/compile-fail/init/invalid_init.rs:19:16 | 19 | bar <- Bar::new(), | -------^^^^^^^^^^ | | | | | the trait `Init` is not implemented for `impl pin_init::PinInit` | required by a bound introduced by this call | = note: if your type implements `PinInit` but not `Init`, you might be forgetting a `#[pin]` annotation on fields Ideally, we would generate differnet message when `PinInit` is implemented but not `Init`; that is not feasible with today's `diagnostics::on_unimplemented` attribute. However, the added note is worth it because in `init!()` is more rarely used compared to `pin_init!()`; in most cases `Init` being unimplemented is the result of missing `#[pin]`. Link: https://patch.msgid.link/20260923-dev-pin-data-diag-v1-5-e4d7193569e5@garyguo.net Signed-off-by: Gary Guo --- rust/pin-init/src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs index 319485dc18ce..d1ed0561bb27 100644 --- a/rust/pin-init/src/lib.rs +++ b/rust/pin-init/src/lib.rs @@ -966,6 +966,9 @@ macro_rules! assert_pinned { #[cfg_attr(not(kernel), doc = "[`Arc`]: alloc::alloc::sync::Arc")] #[cfg_attr(not(kernel), doc = "[`Box`]: alloc::alloc::boxed::Box")] #[must_use = "An initializer must be used in order to create its value."] +#[diagnostic::on_unimplemented( + message = "`{Self}` cannot be used to initialize `{T}` with error `{E}`" +)] pub unsafe trait PinInit: Sized { /// Alias of [`PinInit::__init`]. /// @@ -1100,6 +1103,11 @@ unsafe fn __init(self, slot: *mut T) -> Result<(), E> { #[cfg_attr(not(kernel), doc = "[`Arc`]: alloc::alloc::sync::Arc")] #[cfg_attr(not(kernel), doc = "[`Box`]: alloc::alloc::boxed::Box")] #[must_use = "An initializer must be used in order to create its value."] +#[diagnostic::on_unimplemented( + message = "`{Self}` cannot be used to movably initialize `{T}` with error `{E}`", + note = "if your type implements `PinInit` but not `Init`, \ + you might be forgetting a `#[pin]` annotation on fields" +)] pub unsafe trait Init: PinInit { /// First initializes the value using `self` then calls the function `f` with the initialized /// value.