Skip to content

Commit a380fc4

Browse files
committed
rewrite the initializer macros using syn
Rewrite the initializer macros `[pin_]init!` using `syn`. No functional changes intended aside from improved error messages on syntactic and semantical errors. For example if one forgets to use `<-` with an initializer (and instead uses `:`): impl Bar { fn new() -> impl PinInit<Self> { ... } } impl Foo { fn new() -> impl PinInit<Self> { pin_init!(Self { bar: Bar::new() }) } } Then the declarative macro would report: error[E0308]: mismatched types --> tests/ui/compile-fail/init/colon_instead_of_arrow.rs:21:9 | 14 | fn new() -> impl PinInit<Self> { | ------------------ the found opaque type ... 21 | pin_init!(Self { bar: Bar::new() }) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | expected `Bar`, found opaque type | arguments to this function are incorrect | = note: expected struct `Bar` found opaque type `impl pin_init::PinInit<Bar>` note: function defined here --> $RUST/core/src/ptr/mod.rs | | pub const unsafe fn write<T>(dst: *mut T, src: T) { | ^^^^^ = note: this error originates in the macro `$crate::__init_internal` which comes from the expansion of the macro `pin_init` (in Nightly builds, run with -Z macro-backtrace for more info) And the new error is: error[E0308]: mismatched types --> tests/ui/compile-fail/init/colon_instead_of_arrow.rs:21:31 | 14 | fn new() -> impl PinInit<Self> { | ------------------ the found opaque type ... 21 | pin_init!(Self { bar: Bar::new() }) | --- ^^^^^^^^^^ expected `Bar`, found opaque type | | | arguments to this function are incorrect | = note: expected struct `Bar` found opaque type `impl pin_init::PinInit<Bar>` note: function defined here --> $RUST/core/src/ptr/mod.rs | | pub const unsafe fn write<T>(dst: *mut T, src: T) { | ^^^^^ Importantly, this error gives much more accurate span locations, pointing to the offending field, rather than the entire macro invocation. Signed-off-by: Benno Lossin <[email protected]>
1 parent 3344d50 commit a380fc4

22 files changed

+548
-1193
lines changed

internal/src/init.rs

Lines changed: 432 additions & 0 deletions
Large diffs are not rendered by default.

internal/src/lib.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use proc_macro::TokenStream;
1414
use syn::parse_macro_input;
1515

16+
mod init;
1617
mod pin_data;
1718
mod pinned_drop;
1819
mod zeroable;
@@ -44,3 +45,45 @@ pub fn derive_zeroable(input: TokenStream) -> TokenStream {
4445
pub fn maybe_derive_zeroable(input: TokenStream) -> TokenStream {
4546
zeroable::maybe_derive(parse_macro_input!(input as _)).into()
4647
}
48+
49+
#[proc_macro]
50+
pub fn init(input: TokenStream) -> TokenStream {
51+
init::expand(
52+
parse_macro_input!(input as _),
53+
Some("::core::convert::Infallible"),
54+
false,
55+
)
56+
.into()
57+
}
58+
59+
#[proc_macro]
60+
pub fn pin_init(input: TokenStream) -> TokenStream {
61+
init::expand(
62+
parse_macro_input!(input as _),
63+
Some("::core::convert::Infallible"),
64+
true,
65+
)
66+
.into()
67+
}
68+
69+
#[cfg(kernel)]
70+
#[proc_macro]
71+
pub fn try_init(input: TokenStream) -> TokenStream {
72+
init::expand(
73+
parse_macro_input!(input as _),
74+
Some("::kernel::error::Error"),
75+
false,
76+
)
77+
.into()
78+
}
79+
80+
#[cfg(kernel)]
81+
#[proc_macro]
82+
pub fn try_pin_init(input: TokenStream) -> TokenStream {
83+
init::expand(
84+
parse_macro_input!(input as _),
85+
Some("::kernel::error::Error"),
86+
true,
87+
)
88+
.into()
89+
}

internal/src/pin_data.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ fn generate_projections(
315315
});
316316
quote! {
317317
#[allow(dead_code)]
318+
#[doc(hidden)]
318319
#vis struct #projection #generics {
319320
#(#fields_decl)*
320321
___pin_phantom_data: ::core::marker::PhantomData<&'__pin mut ()>,
@@ -330,6 +331,7 @@ fn generate_projections(
330331
///
331332
/// These fields are **not** structurally pinned:
332333
#(#not_structurally_pinned_fields_docs)*
334+
#[inline]
333335
#vis fn project<'__pin>(
334336
self: ::core::pin::Pin<&'__pin mut Self>,
335337
) -> #projection #ty_gen {
@@ -394,7 +396,7 @@ fn generate_the_pin_data(
394396
quote!(__init),
395397
quote!(&'__slot mut #ty),
396398
quote!(slot),
397-
quote!(#[doc = ""]),
399+
quote!(),
398400
)
399401
};
400402
let slot_safety = format!(

src/lib.rs

Lines changed: 2 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,6 @@ extern crate self as pin_init;
294294

295295
#[doc(hidden)]
296296
pub mod __internal;
297-
#[doc(hidden)]
298-
pub mod macros;
299297

300298
#[cfg(any(feature = "std", feature = "alloc"))]
301299
mod alloc;
@@ -778,32 +776,7 @@ macro_rules! stack_try_pin_init {
778776
/// ```
779777
///
780778
/// [`NonNull<Self>`]: core::ptr::NonNull
781-
// For a detailed example of how this macro works, see the module documentation of the hidden
782-
// module `macros` inside of `macros.rs`.
783-
#[macro_export]
784-
macro_rules! pin_init {
785-
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
786-
$($fields:tt)*
787-
}) => {
788-
$crate::pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
789-
$($fields)*
790-
}? ::core::convert::Infallible)
791-
};
792-
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
793-
$($fields:tt)*
794-
}? $err:ty) => {
795-
$crate::__init_internal!(
796-
@this($($this)?),
797-
@typ($t $(::<$($generics),*>)? ),
798-
@fields($($fields)*),
799-
@error($err),
800-
@data(PinData, use_data),
801-
@has_data(HasPinData, __pin_data),
802-
@construct_closure(pin_init_from_closure),
803-
@munch_fields($($fields)*),
804-
)
805-
}
806-
}
779+
pub use pin_init_internal::pin_init;
807780

808781
/// Construct an in-place, fallible initializer for `struct`s.
809782
///
@@ -841,32 +814,7 @@ macro_rules! pin_init {
841814
/// }
842815
/// # let _ = Box::init(BigBuf::new());
843816
/// ```
844-
// For a detailed example of how this macro works, see the module documentation of the hidden
845-
// module `macros` inside of `macros.rs`.
846-
#[macro_export]
847-
macro_rules! init {
848-
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
849-
$($fields:tt)*
850-
}) => {
851-
$crate::init!($(&$this in)? $t $(::<$($generics),*>)? {
852-
$($fields)*
853-
}? ::core::convert::Infallible)
854-
};
855-
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
856-
$($fields:tt)*
857-
}? $err:ty) => {
858-
$crate::__init_internal!(
859-
@this($($this)?),
860-
@typ($t $(::<$($generics),*>)?),
861-
@fields($($fields)*),
862-
@error($err),
863-
@data(InitData, /*no use_data*/),
864-
@has_data(HasInitData, __init_data),
865-
@construct_closure(init_from_closure),
866-
@munch_fields($($fields)*),
867-
)
868-
}
869-
}
817+
pub use pin_init_internal::init;
870818

871819
/// Asserts that a field on a struct using `#[pin_data]` is marked with `#[pin]` ie. that it is
872820
/// structurally pinned.

0 commit comments

Comments
 (0)