[PATCH 3/3] rust: pin-init: internal: pin_init: provide span for slot projection
From: Gary Guo
Date: Wed Sep 16 2026 - 08:19:55 EST
When initializing a field, pin-init first projects the full slot to a slot
of the field, then initialize it by invoking a method. Currently the span
location is not explicitly set, so the error message points to the full
macro invocation.
Improve it by provide a span, so Rust will point to the specific fields
causing the error when type check fails.
Old error message:
error[E0308]: mismatched types
--> tests/ui/compile-fail/init/field_value_wrong_type.rs:8:28
|
8 | let _ = init!(Foo { a: () });
| ---------------^^---
| | |
| | expected `usize`, found `()`
| arguments to this method are incorrect
New error message:
error[E0308]: mismatched types
--> tests/ui/compile-fail/init/field_value_wrong_type.rs:8:28
|
8 | let _ = init!(Foo { a: () });
| ---^^
| | |
| | expected `usize`, found `()`
| arguments to this method are incorrect
Signed-off-by: Gary Guo <gary@xxxxxxxxxxx>
---
rust/pin-init/internal/src/init.rs | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/rust/pin-init/internal/src/init.rs b/rust/pin-init/internal/src/init.rs
index a77ffef9926b..1d2db93dd33d 100644
--- a/rust/pin-init/internal/src/init.rs
+++ b/rust/pin-init/internal/src/init.rs
@@ -404,9 +404,10 @@ fn init_fields(fields: &Punctuated<InitializerField, Token![,]>, pinned: bool) -
}
};
let ident = member.as_ident();
+ let span = Span::mixed_site().located_at(ident.span());
let slot = if pinned {
- quote_spanned! { Span::mixed_site() =>
+ quote_spanned! { span =>
// SAFETY:
// - `slot` is valid and properly aligned.
// - `make_field_check` checks that `&raw mut (*slot).#member` is properly aligned.
@@ -415,7 +416,7 @@ fn init_fields(fields: &Punctuated<InitializerField, Token![,]>, pinned: bool) -
(unsafe { data.#ident(slot) })
}
} else {
- quote_spanned! { Span::mixed_site() =>
+ quote_spanned! { span =>
// For `init!()` macro, everything is unpinned.
// SAFETY:
// - `&raw mut (*slot).#member` is valid.
@@ -432,6 +433,7 @@ 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 init = match kind {
InitializerKind::Value { value, .. } => {
@@ -440,14 +442,13 @@ fn init_fields(fields: &Punctuated<InitializerField, Token![,]>, pinned: bool) -
.map(|(_, value)| quote!(#value))
.unwrap_or_else(|| quote!(#member));
- quote! {
+ quote_spanned! { full_span =>
#(#attrs)*
let mut #guard = #slot.write(#value);
-
}
}
InitializerKind::Init { value, .. } => {
- quote! {
+ quote_spanned! { full_span =>
#(#attrs)*
let mut #guard = #slot.init(#value)?;
}
@@ -458,7 +459,7 @@ fn init_fields(fields: &Punctuated<InitializerField, Token![,]>, pinned: bool) -
// A tuple field has no name that could be bound here (the `_0` identifiers are considered
// implementation detail and not user-facing).
let binding = match member {
- Member::Named(ident) => quote! {
+ Member::Named(ident) => quote_spanned! { span =>
#(#cfgs)*
// Allow `non_snake_case` since the same warning is going to be reported for the
// struct field.
--
2.54.0