summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
authorGary Guo <gary@garyguo.net>2026-09-22 22:13:19 +0100
committerGary Guo <gary@garyguo.net>2026-09-25 21:37:44 +0100
commitf201d785cae6febe2be33235f541ef25b2a13240 (patch)
tree14b2e26742ff241504e8ed34d90cd7cf68a407e8 /rust
parentdfb6a037fd586f1ffcba3b143dab58f5c88294d1 (diff)
rust: pin-init: internal: pin_data: use HRTB to work around `trivial_bounds` for `Unpin`
`#[pin_data]` generates a `Unpin` implementation for the user, which requires reasoning using field types. This is rejected by rustc as "trivial bounds", which can only be specified using the `#![feature(trivial_bounds)]`. Currently we use an extra lifetime in `__Unpin` to work around this; use HRTB to introduce a dummy lifetime can achieve the same, which the `Zeroable` implementation already uses. Unify the `Unpin` impl to also use the same HRTB trick that `Zeroable` uses. This produces slightly better error message and slightly shorter expansion. Link: https://patch.msgid.link/20260922211320.1390159-1-gary@kernel.org Signed-off-by: Gary Guo <gary@garyguo.net>
Diffstat (limited to 'rust')
-rw-r--r--rust/pin-init/internal/src/pin_data.rs35
-rw-r--r--rust/pin-init/src/__internal.rs16
2 files changed, 12 insertions, 39 deletions
diff --git a/rust/pin-init/internal/src/pin_data.rs b/rust/pin-init/internal/src/pin_data.rs
index 8cd9bf139567..55c627499b35 100644
--- a/rust/pin-init/internal/src/pin_data.rs
+++ b/rust/pin-init/internal/src/pin_data.rs
@@ -5,10 +5,10 @@ use quote::{format_ident, quote, ToTokens};
use syn::{
parse::{End, Nothing, Parse},
parse_quote, parse_quote_spanned,
+ punctuated::Punctuated,
spanned::Spanned,
visit_mut::VisitMut,
Field, Fields, Generics, Ident, Index, Item, Member, PathSegment, Type, TypePath, Visibility,
- WhereClause,
};
use crate::{
@@ -231,21 +231,11 @@ fn generate_unpin_impl(
generics: &Generics,
fields: &[FieldInfo<'_>],
) -> TokenStream {
- let (_, ty_generics, _) = generics.split_for_impl();
- let mut generics_with_pin_lt = generics.clone();
- generics_with_pin_lt.params.insert(0, parse_quote!('__pin));
- generics_with_pin_lt.make_where_clause();
- let (
- impl_generics_with_pin_lt,
- ty_generics_with_pin_lt,
- Some(WhereClause {
- where_token,
- predicates,
- }),
- ) = generics_with_pin_lt.split_for_impl()
- else {
- unreachable!()
- };
+ let (impl_generics, ty_generics, whr) = generics.split_for_impl();
+ let predicates = whr
+ .map(|x| &x.predicates)
+ .unwrap_or(const { &Punctuated::new() });
+
let pinned_fields = fields.iter().filter(|f| f.pinned).map(|f| {
let ident = f.member.as_ident();
let ty = &f.field.ty;
@@ -260,19 +250,18 @@ fn generate_unpin_impl(
dead_code, // The fields below are never used.
non_snake_case // The warning will be emitted on the struct definition.
)]
- struct __Unpin #generics_with_pin_lt
- #where_token
- #predicates
+ struct __Unpin #generics #whr
{
- __phantom_pin: ::pin_init::__internal::PhantomInvariantLifetime<'__pin>,
__phantom: ::pin_init::__internal::PhantomInvariant<#ident #ty_generics>,
#(#pinned_fields),*
}
#[doc(hidden)]
- impl #impl_generics_with_pin_lt ::core::marker::Unpin for #ident #ty_generics
- #where_token
- __Unpin #ty_generics_with_pin_lt: ::core::marker::Unpin,
+ impl #impl_generics ::core::marker::Unpin for #ident #ty_generics
+ where
+ // the `for<'__dummy>` HRTB makes this not error without the `trivial_bounds`
+ // feature <https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956>.
+ for<'__dummy> __Unpin #ty_generics: ::core::marker::Unpin,
#predicates
{}
}
diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
index 8e9fd18b993f..67a354fa29c4 100644
--- a/rust/pin-init/src/__internal.rs
+++ b/rust/pin-init/src/__internal.rs
@@ -42,22 +42,6 @@ impl<T: ?Sized> PhantomInvariant<T> {
}
}
-/// Zero-sized type used to mark a lifetime as invariant.
-///
-/// This is a polyfill for the [unstable type] in the standard library of the same name.
-///
-/// [unstable type]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomInvariantLifetime.html
-#[repr(transparent)]
-#[derive(Clone, Copy, Default)]
-pub struct PhantomInvariantLifetime<'a>(PhantomInvariant<&'a ()>);
-
-impl PhantomInvariantLifetime<'_> {
- #[inline(always)]
- pub const fn new() -> Self {
- Self(PhantomInvariant::new())
- }
-}
-
/// Token type to signify successful initialization.
///
/// Can only be constructed via the unsafe [`Self::new`] function. The initializer macros use this