From e422e205f7c6f5df776654e1250acb8b7d938f40 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 23 Sep 2026 17:51:39 +0100 Subject: [PATCH 1/6] internal: make `__init_data` and `__pin_data` safe Remove the unsafe markers of `__init_data` and `__pin_data`. These methods are for inference help and does not need to be unsafe. The `HasInitData` cannot be implemented outside pin-init, so the `unsafe trait` marker is not necessary. Signed-off-by: Gary Guo --- internal/src/init.rs | 3 +-- internal/src/pin_data.rs | 2 +- src/__internal.rs | 11 +++++------ tests/ui/expand/many_generics.expanded.rs | 2 +- tests/ui/expand/pin-data.expanded.rs | 2 +- tests/ui/expand/pinned_drop.expanded.rs | 2 +- tests/ui/expand/simple-init.expanded.rs | 2 +- tests/ui/expand/tuple_struct.expanded.rs | 6 +++--- 8 files changed, 14 insertions(+), 16 deletions(-) diff --git a/internal/src/init.rs b/internal/src/init.rs index 1d2db93d..1957be83 100644 --- a/internal/src/init.rs +++ b/internal/src/init.rs @@ -312,8 +312,7 @@ fn expand( let field_check = make_field_check(&fields, init_kind, &path); Ok(quote_spanned! { Span::mixed_site() => { // Get the data about fields from the supplied type. - // SAFETY: TODO - let data = unsafe { + let data = { use ::pin_init::__internal::#has_data_trait; // Can't use `<#path as #has_data_trait>::#get_data`, since the user is able to omit // generics (which need to be present with that syntax). diff --git a/internal/src/pin_data.rs b/internal/src/pin_data.rs index 8cd9bf13..30d9b8b5 100644 --- a/internal/src/pin_data.rs +++ b/internal/src/pin_data.rs @@ -538,7 +538,7 @@ fn generate_the_pin_data( type PinData = __ThePinData #ty_generics; #[inline] - unsafe fn __pin_data() -> Self::PinData { + fn __pin_data() -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new() } } } diff --git a/src/__internal.rs b/src/__internal.rs index 8e9fd18b..51f6b40d 100644 --- a/src/__internal.rs +++ b/src/__internal.rs @@ -81,12 +81,12 @@ impl InitOk { /// /// # Safety /// -/// Only the `init` module is allowed to use this trait. +/// `pin-init` relies on the correctness of the helper functions defined on `PinData`. +/// Thus, only the `#[pin_data]` can implement this trait. pub unsafe trait HasPinData { type PinData; - #[expect(clippy::missing_safety_doc)] - unsafe fn __pin_data() -> Self::PinData; + fn __pin_data() -> Self::PinData; } /// This trait is automatically implemented for every type. It aims to provide the same type @@ -98,8 +98,7 @@ pub unsafe trait HasPinData { pub unsafe trait HasInitData { type InitData; - #[expect(clippy::missing_safety_doc)] - unsafe fn __init_data() -> Self::InitData; + fn __init_data() -> Self::InitData; } pub struct AllData(PhantomInvariant); @@ -129,7 +128,7 @@ unsafe impl HasInitData for T { type InitData = AllData; #[inline] - unsafe fn __init_data() -> Self::InitData { + fn __init_data() -> Self::InitData { AllData(PhantomInvariant::new()) } } diff --git a/tests/ui/expand/many_generics.expanded.rs b/tests/ui/expand/many_generics.expanded.rs index 4007476e..f054d36d 100644 --- a/tests/ui/expand/many_generics.expanded.rs +++ b/tests/ui/expand/many_generics.expanded.rs @@ -155,7 +155,7 @@ const _: () = { { type PinData = __ThePinData<'a, 'b, T, SIZE>; #[inline] - unsafe fn __pin_data() -> Self::PinData { + fn __pin_data() -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new(), } diff --git a/tests/ui/expand/pin-data.expanded.rs b/tests/ui/expand/pin-data.expanded.rs index c29811a1..b0f3f199 100644 --- a/tests/ui/expand/pin-data.expanded.rs +++ b/tests/ui/expand/pin-data.expanded.rs @@ -94,7 +94,7 @@ const _: () = { unsafe impl ::pin_init::__internal::HasPinData for Foo { type PinData = __ThePinData; #[inline] - unsafe fn __pin_data() -> Self::PinData { + fn __pin_data() -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new(), } diff --git a/tests/ui/expand/pinned_drop.expanded.rs b/tests/ui/expand/pinned_drop.expanded.rs index bd1ff78a..be603c26 100644 --- a/tests/ui/expand/pinned_drop.expanded.rs +++ b/tests/ui/expand/pinned_drop.expanded.rs @@ -94,7 +94,7 @@ const _: () = { unsafe impl ::pin_init::__internal::HasPinData for Foo { type PinData = __ThePinData; #[inline] - unsafe fn __pin_data() -> Self::PinData { + fn __pin_data() -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new(), } diff --git a/tests/ui/expand/simple-init.expanded.rs b/tests/ui/expand/simple-init.expanded.rs index 0dfc1cb4..fa621a24 100644 --- a/tests/ui/expand/simple-init.expanded.rs +++ b/tests/ui/expand/simple-init.expanded.rs @@ -2,7 +2,7 @@ use pin_init::*; struct Foo {} fn main() { let _ = { - let data = unsafe { + let data = { use ::pin_init::__internal::HasInitData; Foo::__init_data() }; diff --git a/tests/ui/expand/tuple_struct.expanded.rs b/tests/ui/expand/tuple_struct.expanded.rs index 61aefecc..d242b443 100644 --- a/tests/ui/expand/tuple_struct.expanded.rs +++ b/tests/ui/expand/tuple_struct.expanded.rs @@ -109,7 +109,7 @@ const _: () = { for Foo<'a, T, N> { type PinData = __ThePinData<'a, T, N>; #[inline] - unsafe fn __pin_data() -> Self::PinData { + fn __pin_data() -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new(), } @@ -142,7 +142,7 @@ const _: () = { fn main() { let mut first = [1u8, 2, 3]; let _ = { - let data = unsafe { + let data = { use ::pin_init::__internal::HasInitData; Foo::__init_data() }; @@ -200,7 +200,7 @@ fn main() { }; let mut second = [4u8, 5, 6]; let _ = { - let data = unsafe { + let data = { use ::pin_init::__internal::HasInitData; Foo::__init_data() }; From 90ccc86d24683203f7ff52c0104f41be564c4fbc Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 23 Sep 2026 18:10:35 +0100 Subject: [PATCH 2/6] internal: remove associated type of `HasInitData` There is only a single implementation, the associated type is not necessary. Remove it, and rename `AllData` to `InitData` to be a more meaningful name. The single implementation also means that "unsafe" is redundant, so remove it as well. Signed-off-by: Gary Guo --- src/__internal.rs | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/src/__internal.rs b/src/__internal.rs index 51f6b40d..c609cd7c 100644 --- a/src/__internal.rs +++ b/src/__internal.rs @@ -89,30 +89,31 @@ pub unsafe trait HasPinData { fn __pin_data() -> Self::PinData; } -/// This trait is automatically implemented for every type. It aims to provide the same type -/// inference help as `HasPinData`. +/// This trait is automatically implemented for every type. /// -/// # Safety -/// -/// Only the `init` module is allowed to use this trait. -pub unsafe trait HasInitData { - type InitData; - - fn __init_data() -> Self::InitData; +/// It aims to provide type inference help; `PATH::__init_data()` would be able to retrieve an +/// instance of `InitData>` without having to mention the generics explicitly. +pub trait HasInitData { + #[inline] + fn __init_data() -> InitData { + InitData(PhantomInvariant::new()) + } } -pub struct AllData(PhantomInvariant); +impl HasInitData for T {} + +pub struct InitData(PhantomInvariant); -impl Clone for AllData { +impl Clone for InitData { #[inline] fn clone(&self) -> Self { *self } } -impl Copy for AllData {} +impl Copy for InitData {} -impl AllData { +impl InitData { /// Type inference helper function. #[inline(always)] pub fn __make_closure(self, f: F) -> F @@ -123,16 +124,6 @@ impl AllData { } } -// SAFETY: TODO. -unsafe impl HasInitData for T { - type InitData = AllData; - - #[inline] - fn __init_data() -> Self::InitData { - AllData(PhantomInvariant::new()) - } -} - /// Stack initializer helper type. Use [`stack_pin_init`] instead of this primitive. /// /// # Invariants From 5ca8c1b5173599a5319e0cfc6634f4651ff4951c Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 23 Sep 2026 18:13:58 +0100 Subject: [PATCH 3/6] internal: use `HasInitData` to provide inference help only Currently, type inference of the initialized type is done by use the function calling syntax `PATH::__pin_data` or `PATH::__init_data` to obtain the required init data type, without needing the user to explicitly mention all generics. Switch to always use `HasInitData::__init_data` to provide that inference, which will not produce method-not-found errors as it is always available. Change `__pin_data` to take `InitData` as the receiver, so for types that require `HasPinData`, `HasPinData::__pin_data(data)` can be used to obtain the needed type without having to mention the user-provided path again. The expanded code also uses the span of the type, so diagnostics will hint to user that the type is causing the issue. With this change, the error message when `HasPinData` is not implemented changes from error[E0599]: no associated function or constant named `__pin_data` found for struct `Foo` in the current scope --> tests/ui/compile-fail/init/missing_pin_data.rs:9:9 | 3 | struct Foo { | ---------- associated function or constant `__pin_data` not found for this struct ... 9 | pin_init!(Self { a: 42 }) | ^^^^^^^^^^^^^^^^^^^^^^^^^ associated function or constant not found in `Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `__pin_data`, perhaps you need to implement it: candidate #1: `pin_init::__internal::HasPinData` to error[E0277]: the trait bound `Foo: pin_init::__internal::HasPinData` is not satisfied --> tests/ui/compile-fail/init/missing_pin_data.rs:9:19 | 9 | pin_init!(Self { a: 42 }) | ^^^^ unsatisfied trait bound | help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo` --> tests/ui/compile-fail/init/missing_pin_data.rs:3:1 | 3 | struct Foo { | ^^^^^^^^^^ Signed-off-by: Gary Guo --- internal/src/init.rs | 22 ++++++++++--------- internal/src/pin_data.rs | 2 +- src/__internal.rs | 2 +- src/lib.rs | 3 ++- .../compile-fail/init/missing_pin_data.stderr | 17 +++++++------- tests/ui/expand/many_generics.expanded.rs | 2 +- tests/ui/expand/pin-data.expanded.rs | 2 +- tests/ui/expand/pinned_drop.expanded.rs | 2 +- tests/ui/expand/tuple_struct.expanded.rs | 2 +- 9 files changed, 28 insertions(+), 26 deletions(-) diff --git a/internal/src/init.rs b/internal/src/init.rs index 1957be83..e98182c6 100644 --- a/internal/src/init.rs +++ b/internal/src/init.rs @@ -269,18 +269,17 @@ fn expand( }, |(_, err)| Box::new(err), ); - let (has_data_trait, get_data, init_from_closure) = if pinned { + let (get_pin_data, init_from_closure) = if pinned { ( - format_ident!("HasPinData"), - format_ident!("__pin_data"), + Some( + quote_spanned! { path.span().resolved_at(Span::mixed_site()) => + let data = ::pin_init::__internal::HasPinData::__pin_data(data); + }, + ), format_ident!("pin_init_from_closure"), ) } else { - ( - format_ident!("HasInitData"), - format_ident!("__init_data"), - format_ident!("init_from_closure"), - ) + (None, format_ident!("init_from_closure")) }; let init_kind = get_init_kind(rest, dcx); let zeroable_check = match init_kind { @@ -313,11 +312,14 @@ fn expand( Ok(quote_spanned! { Span::mixed_site() => { // Get the data about fields from the supplied type. let data = { - use ::pin_init::__internal::#has_data_trait; + use ::pin_init::__internal::HasInitData; // Can't use `<#path as #has_data_trait>::#get_data`, since the user is able to omit // generics (which need to be present with that syntax). - #path::#get_data() + #path::__init_data() }; + + #get_pin_data + // Ensure that `data` really is of type `data` and help with type inference: let init = data.__make_closure::<_, #error>( move |slot| { diff --git a/internal/src/pin_data.rs b/internal/src/pin_data.rs index 30d9b8b5..a12e5a44 100644 --- a/internal/src/pin_data.rs +++ b/internal/src/pin_data.rs @@ -538,7 +538,7 @@ fn generate_the_pin_data( type PinData = __ThePinData #ty_generics; #[inline] - fn __pin_data() -> Self::PinData { + fn __pin_data(_: ::pin_init::__internal::InitData) -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new() } } } diff --git a/src/__internal.rs b/src/__internal.rs index c609cd7c..1f3a9cc0 100644 --- a/src/__internal.rs +++ b/src/__internal.rs @@ -86,7 +86,7 @@ impl InitOk { pub unsafe trait HasPinData { type PinData; - fn __pin_data() -> Self::PinData; + fn __pin_data(_: InitData) -> Self::PinData; } /// This trait is automatically implemented for every type. diff --git a/src/lib.rs b/src/lib.rs index 41105903..319485dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -920,7 +920,8 @@ macro_rules! assert_pinned { ($ty:ty, $field:ident, $field_ty:ty, inline) => { // SAFETY: This code is unreachable. let _ = move |ptr: *mut $ty| unsafe { - let data = <$ty as $crate::__internal::HasPinData>::__pin_data(); + let data = <$ty as $crate::__internal::HasInitData>::__init_data(); + let data = $crate::__internal::HasPinData::__pin_data(data); _ = data .$field(ptr) .init($crate::__internal::AlwaysFail::<$field_ty>::new()); diff --git a/tests/ui/compile-fail/init/missing_pin_data.stderr b/tests/ui/compile-fail/init/missing_pin_data.stderr index 03cdfe28..8928f73c 100644 --- a/tests/ui/compile-fail/init/missing_pin_data.stderr +++ b/tests/ui/compile-fail/init/missing_pin_data.stderr @@ -1,13 +1,12 @@ -error[E0599]: no associated function or constant named `__pin_data` found for struct `Foo` in the current scope - --> tests/ui/compile-fail/init/missing_pin_data.rs:9:9 +error[E0277]: the trait bound `Foo: pin_init::__internal::HasPinData` is not satisfied + --> tests/ui/compile-fail/init/missing_pin_data.rs:9:19 | -3 | struct Foo { - | ---------- associated function or constant `__pin_data` not found for this struct -... 9 | pin_init!(Self { a: 42 }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^ associated function or constant not found in `Foo` + | ^^^^ unsatisfied trait bound + | +help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo` + --> tests/ui/compile-fail/init/missing_pin_data.rs:3:1 | - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `__pin_data`, perhaps you need to implement it: - candidate #1: `pin_init::__internal::HasPinData` +3 | struct Foo { + | ^^^^^^^^^^ = note: this error originates in the macro `pin_init` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/expand/many_generics.expanded.rs b/tests/ui/expand/many_generics.expanded.rs index f054d36d..dd337b02 100644 --- a/tests/ui/expand/many_generics.expanded.rs +++ b/tests/ui/expand/many_generics.expanded.rs @@ -155,7 +155,7 @@ const _: () = { { type PinData = __ThePinData<'a, 'b, T, SIZE>; #[inline] - fn __pin_data() -> Self::PinData { + fn __pin_data(_: ::pin_init::__internal::InitData) -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new(), } diff --git a/tests/ui/expand/pin-data.expanded.rs b/tests/ui/expand/pin-data.expanded.rs index b0f3f199..f4846594 100644 --- a/tests/ui/expand/pin-data.expanded.rs +++ b/tests/ui/expand/pin-data.expanded.rs @@ -94,7 +94,7 @@ const _: () = { unsafe impl ::pin_init::__internal::HasPinData for Foo { type PinData = __ThePinData; #[inline] - fn __pin_data() -> Self::PinData { + fn __pin_data(_: ::pin_init::__internal::InitData) -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new(), } diff --git a/tests/ui/expand/pinned_drop.expanded.rs b/tests/ui/expand/pinned_drop.expanded.rs index be603c26..aa5efec1 100644 --- a/tests/ui/expand/pinned_drop.expanded.rs +++ b/tests/ui/expand/pinned_drop.expanded.rs @@ -94,7 +94,7 @@ const _: () = { unsafe impl ::pin_init::__internal::HasPinData for Foo { type PinData = __ThePinData; #[inline] - fn __pin_data() -> Self::PinData { + fn __pin_data(_: ::pin_init::__internal::InitData) -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new(), } diff --git a/tests/ui/expand/tuple_struct.expanded.rs b/tests/ui/expand/tuple_struct.expanded.rs index d242b443..9944a0c3 100644 --- a/tests/ui/expand/tuple_struct.expanded.rs +++ b/tests/ui/expand/tuple_struct.expanded.rs @@ -109,7 +109,7 @@ const _: () = { for Foo<'a, T, N> { type PinData = __ThePinData<'a, T, N>; #[inline] - fn __pin_data() -> Self::PinData { + fn __pin_data(_: ::pin_init::__internal::InitData) -> Self::PinData { __ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new(), } From c9fa61b6bf1b77e5e4101c836b647dd3ba93b53f Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 23 Sep 2026 18:19:16 +0100 Subject: [PATCH 4/6] internal: add custom diagnostic when `#[pin_data]` is not implemented Produce a more helpful error message when `#[pin_data]` is omitted. The error message changes from error[E0277]: the trait bound `Foo: pin_init::__internal::HasPinData` is not satisfied --> tests/ui/compile-fail/init/missing_pin_data.rs:9:19 | 9 | pin_init!(Self { a: 42 }) | ^^^^ unsatisfied trait bound | help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo` --> tests/ui/compile-fail/init/missing_pin_data.rs:3:1 | 3 | struct Foo { | ^^^^^^^^^^ to error[E0277]: `Foo` cannot be used with `pin_init!` macro --> tests/ui/compile-fail/init/missing_pin_data.rs:9:19 | 9 | pin_init!(Self { a: 42 }) | ^^^^ unsatisfied trait bound | help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo` --> tests/ui/compile-fail/init/missing_pin_data.rs:3:1 | 3 | struct Foo { | ^^^^^^^^^^ = note: did you forget to add `#[pin_data]` attribute to the struct? Signed-off-by: Gary Guo --- src/__internal.rs | 4 ++++ tests/ui/compile-fail/init/missing_pin_data.stderr | 3 ++- .../pinned_drop/no_pin_data_but_pinned_drop.stderr | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/__internal.rs b/src/__internal.rs index 1f3a9cc0..f924fe57 100644 --- a/src/__internal.rs +++ b/src/__internal.rs @@ -83,6 +83,10 @@ impl InitOk { /// /// `pin-init` relies on the correctness of the helper functions defined on `PinData`. /// Thus, only the `#[pin_data]` can implement this trait. +#[diagnostic::on_unimplemented( + message = "`{Self}` cannot be used with `pin_init!` macro", + note = "did you forget to add `#[pin_data]` attribute to the struct?" +)] pub unsafe trait HasPinData { type PinData; diff --git a/tests/ui/compile-fail/init/missing_pin_data.stderr b/tests/ui/compile-fail/init/missing_pin_data.stderr index 8928f73c..32899257 100644 --- a/tests/ui/compile-fail/init/missing_pin_data.stderr +++ b/tests/ui/compile-fail/init/missing_pin_data.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `Foo: pin_init::__internal::HasPinData` is not satisfied +error[E0277]: `Foo` cannot be used with `pin_init!` macro --> tests/ui/compile-fail/init/missing_pin_data.rs:9:19 | 9 | pin_init!(Self { a: 42 }) @@ -9,4 +9,5 @@ help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo` | 3 | struct Foo { | ^^^^^^^^^^ + = note: did you forget to add `#[pin_data]` attribute to the struct? = note: this error originates in the macro `pin_init` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/compile-fail/pinned_drop/no_pin_data_but_pinned_drop.stderr b/tests/ui/compile-fail/pinned_drop/no_pin_data_but_pinned_drop.stderr index 80f94c62..9b721c91 100644 --- a/tests/ui/compile-fail/pinned_drop/no_pin_data_but_pinned_drop.stderr +++ b/tests/ui/compile-fail/pinned_drop/no_pin_data_but_pinned_drop.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `Foo: pin_init::__internal::HasPinData` is not satisfied +error[E0277]: `Foo` cannot be used with `pin_init!` macro --> tests/ui/compile-fail/pinned_drop/no_pin_data_but_pinned_drop.rs:7:21 | 7 | impl PinnedDrop for Foo { @@ -9,6 +9,7 @@ help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo` | 4 | struct Foo {} | ^^^^^^^^^^ + = note: did you forget to add `#[pin_data]` attribute to the struct? note: required by a bound in `PinnedDrop` --> src/lib.rs | From 6de454becb4cf1a09ac058b628bc44228271f583 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 23 Sep 2026 18:41:01 +0100 Subject: [PATCH 5/6] 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]`. Signed-off-by: Gary Guo --- src/lib.rs | 8 ++++++++ tests/ui/compile-fail/init/invalid_init.stderr | 3 ++- tests/ui/compile-fail/pin_data/missing_pin.stderr | 3 ++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 319485dc..d1ed0561 100644 --- a/src/lib.rs +++ b/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 @@ where #[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. diff --git a/tests/ui/compile-fail/init/invalid_init.stderr b/tests/ui/compile-fail/init/invalid_init.stderr index 6c10c0de..a8a57f19 100644 --- a/tests/ui/compile-fail/init/invalid_init.stderr +++ b/tests/ui/compile-fail/init/invalid_init.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `impl pin_init::PinInit: Init` is not satisfied +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(), @@ -7,6 +7,7 @@ error[E0277]: the trait bound `impl pin_init::PinInit: Init` is not | | 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 help: the following other types implement trait `Init` --> src/lib.rs | diff --git a/tests/ui/compile-fail/pin_data/missing_pin.stderr b/tests/ui/compile-fail/pin_data/missing_pin.stderr index d28ef460..7225cd1b 100644 --- a/tests/ui/compile-fail/pin_data/missing_pin.stderr +++ b/tests/ui/compile-fail/pin_data/missing_pin.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `impl PinInit: Init` is not satisfied +error[E0277]: `impl PinInit` cannot be used to movably initialize `usize` with error `_` --> tests/ui/compile-fail/pin_data/missing_pin.rs:12:18 | 12 | a <- a, @@ -7,6 +7,7 @@ error[E0277]: the trait bound `impl PinInit: Init` is not satis | | the trait `Init` is not implemented for `impl 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 help: the trait `Init` is not implemented for `impl PinInit` but trait `Init, !>` is implemented for it --> src/lib.rs From a58efaa4a58c273d13c663e840f9c265951f6751 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 25 Sep 2026 12:47:54 +0100 Subject: [PATCH 6/6] ci: make `checkpatch.pl` failure non-fatal Signed-off-by: Gary Guo --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9fc01aa..c34b3db6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -449,6 +449,7 @@ jobs: fi working-directory: pin-init - name: Run checkpatch.pl + continue-on-error: true run: | if [ "$(git rev-parse HEAD)" = "$(git rev-parse origin/pin-init-next)" ]; then # when there are no new commits, we can succeed directly