* [PATCH 0/3] rust: pin-init: upstream synchronization for 7.4
@ 2026-09-28 17:32 Gary Guo
2026-09-28 17:32 ` [PATCH 1/3] rust: pin-init: internal: init: allow reborrow of `Pin<&mut T>` bindings Gary Guo
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Gary Guo @ 2026-09-28 17:32 UTC (permalink / raw)
To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan
Cc: rust-for-linux, linux-kernel, Gary Guo
This sync series contain two upstream PRs:
- Several additional diagnostics improvements
https://github.com/Rust-for-Linux/pin-init/pull/179
- internal: init: allow reborrow of Pin<&mut T> bindings
https://github.com/Rust-for-Linux/pin-init/pull/180
The upstream PRs have test suites coverage which is not part of the kernel
tree. Reviews/testings are welcome from either GitHub or the mailing list.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
Gary Guo (3):
rust: pin-init: internal: init: allow reborrow of `Pin<&mut T>` bindings
rust: pin-init: internal: init: improve diagnostics from field checks
rust: pin-init: internal: init: use span of `<-` or `:` for the init/write call.
rust/pin-init/internal/src/init.rs | 106 +++++++++++++++++++++++++------------
1 file changed, 71 insertions(+), 35 deletions(-)
---
base-commit: 95593ed3616194c9498cc190cd1a3693ff4bca37
change-id: 20260928-dev-pin-init-sync-93e81b019c3c
Best regards,
--
Gary Guo <gary@garyguo.net>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] rust: pin-init: internal: init: allow reborrow of `Pin<&mut T>` bindings
2026-09-28 17:32 [PATCH 0/3] rust: pin-init: upstream synchronization for 7.4 Gary Guo
@ 2026-09-28 17:32 ` Gary Guo
2026-09-29 19:17 ` Danilo Krummrich
2026-09-28 17:32 ` [PATCH 2/3] rust: pin-init: internal: init: improve diagnostics from field checks Gary Guo
2026-09-28 17:32 ` [PATCH 3/3] rust: pin-init: internal: init: use span of `<-` or `:` for the init/write call Gary Guo
2 siblings, 1 reply; 5+ messages in thread
From: Gary Guo @ 2026-09-28 17:32 UTC (permalink / raw)
To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan
Cc: rust-for-linux, linux-kernel, Gary Guo
Use `let mut` for created bindings of initialized field, so `Pin<&mut T>`
bindings may be reborrowed in subsequent initializers or code blocks.
Without `let mut`, attempt to reborrow can produce error (and also a
confusing fix):
error[E0596]: cannot borrow `gpu` as mutable, as it is not declared as mutable
--> drivers/gpu/nova-core/driver.rs:129:17
|
129 | gpu.as_mut().run_selftests(pdev);
| ^^^ cannot borrow as mutable
|
help: consider changing this to be mutable |
119 | mut gpu <- Gpu::new(
| +++
error: aborting due to 1 previous error
Reported-by: Danilo Krummrich <dakr@kernel.org>
Closes: https://lore.kernel.org/nova-gpu/DLQXWXRP3P1J.28SLFOJJQ2EDK@kernel.org/
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/pin-init/internal/src/init.rs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/rust/pin-init/internal/src/init.rs b/rust/pin-init/internal/src/init.rs
index c5b5a0ce5c4e..4e77c7af86f9 100644
--- a/rust/pin-init/internal/src/init.rs
+++ b/rust/pin-init/internal/src/init.rs
@@ -446,7 +446,8 @@ fn init_fields(fields: &Punctuated<InitializerField, Token![,]>, pinned: bool) -
// Allow `non_snake_case` since the same warning is going to be reported for the
// struct field.
#[allow(unused_variables, non_snake_case)]
- let #ident = #guard.let_binding();
+ // Include `mut` so that `Pin<&mut T>` bindings can be reborrowed via `.as_mut()`.
+ let mut #ident = #guard.let_binding();
},
Member::Unnamed(_) => quote!(),
};
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/3] rust: pin-init: internal: init: improve diagnostics from field checks
2026-09-28 17:32 [PATCH 0/3] rust: pin-init: upstream synchronization for 7.4 Gary Guo
2026-09-28 17:32 ` [PATCH 1/3] rust: pin-init: internal: init: allow reborrow of `Pin<&mut T>` bindings Gary Guo
@ 2026-09-28 17:32 ` Gary Guo
2026-09-28 17:32 ` [PATCH 3/3] rust: pin-init: internal: init: use span of `<-` or `:` for the init/write call Gary Guo
2 siblings, 0 replies; 5+ messages in thread
From: Gary Guo @ 2026-09-28 17:32 UTC (permalink / raw)
To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan
Cc: rust-for-linux, linux-kernel, Gary Guo
Use span of the field name for generated alignment and field duplication
checks. This avoids pointing diagnostics to the full macro invocation, but
just the part of it going wrong.
Before the change:
error[E0062]: field `0` specified more than once
--> tests/ui/compile-fail/init/tuple_duplicate_field.rs:7:37
|
7 | let _ = pin_init!(Tuple { 0: 1, 0: 2, 1: 3 });
| ------------------------^------------
| | |
| | used more than once
| first use of `0`
After the change:
error[E0062]: field `0` specified more than once
--> tests/ui/compile-fail/init/tuple_duplicate_field.rs:7:37
|
7 | let _ = pin_init!(Tuple { 0: 1, 0: 2, 1: 3 });
| - ^ used more than once
| |
| first use of `0`
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/pin-init/internal/src/init.rs | 65 ++++++++++++++++++++++++--------------
1 file changed, 42 insertions(+), 23 deletions(-)
diff --git a/rust/pin-init/internal/src/init.rs b/rust/pin-init/internal/src/init.rs
index 4e77c7af86f9..f6f3e2f8cda6 100644
--- a/rust/pin-init/internal/src/init.rs
+++ b/rust/pin-init/internal/src/init.rs
@@ -478,42 +478,61 @@ fn make_field_check(
init_kind: InitKind,
path: &Path,
) -> TokenStream {
- let field_attrs: Vec<_> = fields
+ let align_checks: TokenStream = fields
.iter()
- .filter_map(|f| f.kind.member().map(|_| &f.attrs))
+ .filter_map(|f| {
+ let member = f.kind.member()?;
+ let span = member.span().resolved_at(Span::mixed_site());
+ let attrs = &f.attrs;
+
+ Some(quote_spanned! {span =>
+ // Create references to ensure that the initialized field is properly aligned.
+ // Unaligned fields will cause the compiler to emit E0793. We do not support
+ // unaligned fields since `Init::__init` requires an aligned pointer; the call to
+ // `ptr::write` for value-initialization case has the same requirement.
+ #(#attrs)*
+ let _ = &(*slot).#member;
+ })
+ })
+ .collect();
+
+ let fake_field_init: TokenStream = fields
+ .iter()
+ .filter_map(|f| {
+ let member = f.kind.member()?;
+ let span = member.span().resolved_at(Span::mixed_site());
+ let attrs = &f.attrs;
+
+ Some(quote_spanned! {span =>
+ #(#attrs)*
+ #member: loop {},
+ })
+ })
.collect();
- let field_name: Vec<_> = fields.iter().filter_map(|f| f.kind.member()).collect();
let zeroing_trailer = match init_kind {
InitKind::Normal => None,
InitKind::Zeroing => Some(quote! {
..::core::mem::zeroed()
}),
};
+ let field_dup_checks = quote_spanned! { Span::mixed_site() =>
+ // If the zeroing trailer is not present, this checks that all fields have been
+ // mentioned exactly once. If the zeroing trailer is present, all missing fields will be
+ // zeroed, so this checks that all fields have been mentioned at most once. The use of
+ // struct initializer will still generate very natural error messages for any misuse.
+ ::core::ptr::write(slot, #path {
+ #fake_field_init
+ #zeroing_trailer
+ })
+ };
+
quote_spanned! { Span::mixed_site() =>
#[allow(unreachable_code)]
// We use unreachable code to perform field checks. They're still checked by the compiler.
// SAFETY: this code is never executed.
let _ = || unsafe {
- // Create references to ensure that the initialized field is properly aligned.
- // Unaligned fields will cause the compiler to emit E0793. We do not support
- // unaligned fields since `Init::__init` requires an aligned pointer; the call to
- // `ptr::write` for value-initialization case has the same requirement.
- #(
- #(#field_attrs)*
- let _ = &(*slot).#field_name;
- )*
-
- // If the zeroing trailer is not present, this checks that all fields have been
- // mentioned exactly once. If the zeroing trailer is present, all missing fields will be
- // zeroed, so this checks that all fields have been mentioned at most once. The use of
- // struct initializer will still generate very natural error messages for any misuse.
- ::core::ptr::write(slot, #path {
- #(
- #(#field_attrs)*
- #field_name: loop {},
- )*
- #zeroing_trailer
- })
+ #align_checks
+ #field_dup_checks
};
}
}
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 3/3] rust: pin-init: internal: init: use span of `<-` or `:` for the init/write call.
2026-09-28 17:32 [PATCH 0/3] rust: pin-init: upstream synchronization for 7.4 Gary Guo
2026-09-28 17:32 ` [PATCH 1/3] rust: pin-init: internal: init: allow reborrow of `Pin<&mut T>` bindings Gary Guo
2026-09-28 17:32 ` [PATCH 2/3] rust: pin-init: internal: init: improve diagnostics from field checks Gary Guo
@ 2026-09-28 17:32 ` Gary Guo
2 siblings, 0 replies; 5+ messages in thread
From: Gary Guo @ 2026-09-28 17:32 UTC (permalink / raw)
To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan
Cc: rust-for-linux, linux-kernel, Gary Guo
Currently we use the full span of the field initializer as the span of the
generated init call. This produces overlapping spans for type mismatch
errors, which is hard to read.
Use the span of `<-` or `:` for the method name, which wll cause type
mismatch errors or trait bound not implemented error to be appear from the
`<-` or `:` token, which declutter the output a bit and make it easier to
read.
Before the change:
error[E0277]: `impl pin_init::PinInit<Bar>` 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<Bar, _>` is not implemented for `impl pin_init::PinInit<Bar>`
| 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
After the change:
error[E0277]: `impl pin_init::PinInit<Bar>` 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<Bar, _>` is not implemented for `impl pin_init::PinInit<Bar>`
| |
| 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
Suggested-by: Benno Lossin <lossin@kernel.org>
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/pin-init/internal/src/init.rs | 38 +++++++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 11 deletions(-)
diff --git a/rust/pin-init/internal/src/init.rs b/rust/pin-init/internal/src/init.rs
index f6f3e2f8cda6..6605e04d49df 100644
--- a/rust/pin-init/internal/src/init.rs
+++ b/rust/pin-init/internal/src/init.rs
@@ -101,7 +101,7 @@ enum InitializerKind {
},
Init {
member: Member,
- _left_arrow_token: Token![<-],
+ left_arrow_token: Token![<-],
value: Expr,
},
Code {
@@ -415,24 +415,40 @@ fn init_fields(fields: &Punctuated<InitializerField, Token![,]>, pinned: bool) -
// `mixed_site` ensures that the guard is not accessible to the user-controlled code.
let guard = format_ident!("__{ident}_guard", span = Span::mixed_site());
- let full_span = kind.span();
+ let full_span = kind.span().resolved_at(Span::mixed_site());
let init = match kind {
InitializerKind::Value { value, .. } => {
- let value = value
+ let (colon_span, value) = value
.as_ref()
- .map(|(_, value)| quote!(#value))
- .unwrap_or_else(|| quote!(#member));
+ .map(|(colon_token, value)| (colon_token.span(), quote!(#value)))
+ .unwrap_or_else(|| (member.span(), quote!(#member)));
+
+ // Use `:` as the span of the method name, so the type requirement appears to come
+ // from `:`.
+ let write =
+ format_ident!("write", span = colon_span.resolved_at(Span::mixed_site()));
quote_spanned! { full_span =>
#(#attrs)*
- let mut #guard = #slot.write(#value);
+ let mut #guard = #slot.#write(#value);
}
}
- InitializerKind::Init { value, .. } => {
+ InitializerKind::Init {
+ value,
+ left_arrow_token,
+ ..
+ } => {
+ // Use `<-` as the span of the method name, so the trait bound appears to come from
+ // `<-`.
+ let init = format_ident!(
+ "init",
+ span = left_arrow_token.span().resolved_at(Span::mixed_site())
+ );
+
quote_spanned! { full_span =>
#(#attrs)*
- let mut #guard = #slot.init(#value)?;
+ let mut #guard = #slot.#init(#value)?;
}
}
InitializerKind::Code { .. } => unreachable!(),
@@ -690,7 +706,7 @@ fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
if lh.peek(Token![<-]) {
Ok(Self::Init {
member,
- _left_arrow_token: input.parse()?,
+ left_arrow_token: input.parse()?,
value: input.parse()?,
})
} else if lh.peek(Token![:]) {
@@ -819,11 +835,11 @@ fn to_tokens(&self, tokens: &mut TokenStream) {
}
Self::Init {
member,
- _left_arrow_token,
+ left_arrow_token,
value,
} => {
member.to_tokens(tokens);
- _left_arrow_token.to_tokens(tokens);
+ left_arrow_token.to_tokens(tokens);
value.to_tokens(tokens);
}
Self::Code {
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/3] rust: pin-init: internal: init: allow reborrow of `Pin<&mut T>` bindings
2026-09-28 17:32 ` [PATCH 1/3] rust: pin-init: internal: init: allow reborrow of `Pin<&mut T>` bindings Gary Guo
@ 2026-09-29 19:17 ` Danilo Krummrich
0 siblings, 0 replies; 5+ messages in thread
From: Danilo Krummrich @ 2026-09-29 19:17 UTC (permalink / raw)
To: Gary Guo
Cc: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Daniel Almeida,
Tamir Duberstein, Alexandre Courbot, Onur Özkan,
rust-for-linux, linux-kernel
On 9/28/26 7:32 PM, Gary Guo wrote:
> Use `let mut` for created bindings of initialized field, so `Pin<&mut T>`
> bindings may be reborrowed in subsequent initializers or code blocks.
>
> Without `let mut`, attempt to reborrow can produce error (and also a
> confusing fix):
>
> error[E0596]: cannot borrow `gpu` as mutable, as it is not declared as mutable
> --> drivers/gpu/nova-core/driver.rs:129:17
> |
> 129 | gpu.as_mut().run_selftests(pdev);
> | ^^^ cannot borrow as mutable
> |
> help: consider changing this to be mutable |
> 119 | mut gpu <- Gpu::new(
> | +++
>
> error: aborting due to 1 previous error
>
> Reported-by: Danilo Krummrich <dakr@kernel.org>
> Closes: https://lore.kernel.org/nova-gpu/DLQXWXRP3P1J.28SLFOJJQ2EDK@kernel.org/
> Signed-off-by: Gary Guo <gary@garyguo.net>
Tested-by: Danilo Krummrich <dakr@kernel.org>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-29 19:17 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-28 17:32 [PATCH 0/3] rust: pin-init: upstream synchronization for 7.4 Gary Guo
2026-09-28 17:32 ` [PATCH 1/3] rust: pin-init: internal: init: allow reborrow of `Pin<&mut T>` bindings Gary Guo
2026-09-29 19:17 ` Danilo Krummrich
2026-09-28 17:32 ` [PATCH 2/3] rust: pin-init: internal: init: improve diagnostics from field checks Gary Guo
2026-09-28 17:32 ` [PATCH 3/3] rust: pin-init: internal: init: use span of `<-` or `:` for the init/write call Gary Guo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®