Skip to content

Commit d59c2fb

Browse files
committed
internal: make make_closure inherent methods
The `InitData` and `PinData` trait does not need to exist, the inference helpers could be inherent methods instead. There is no risk for calling the wrong methods even when user defines it, as inherent methods take priority over trait methods. With this change, we can use `impl Trait` as the return type of these methods. Thus, return `impl Init` or `impl PinInit` directly and simplify the code generation of `init!` and `pin_init!` macro. The method is renamed to `__make_init` accordingly. Signed-off-by: Gary Guo <gary@garyguo.net>
1 parent ae25376 commit d59c2fb

7 files changed

Lines changed: 105 additions & 87 deletions

File tree

internal/src/init.rs

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,10 @@ pub(crate) fn expand(
103103
|(_, err)| Box::new(err),
104104
);
105105
let slot = format_ident!("slot");
106-
let (has_data_trait, data_trait, get_data, init_from_closure) = if pinned {
107-
(
108-
format_ident!("HasPinData"),
109-
format_ident!("PinData"),
110-
format_ident!("__pin_data"),
111-
format_ident!("pin_init_from_closure"),
112-
)
106+
let (has_data_trait, get_data) = if pinned {
107+
(format_ident!("HasPinData"), format_ident!("__pin_data"))
113108
} else {
114-
(
115-
format_ident!("HasInitData"),
116-
format_ident!("InitData"),
117-
format_ident!("__init_data"),
118-
format_ident!("init_from_closure"),
119-
)
109+
(format_ident!("HasInitData"), format_ident!("__init_data"))
120110
};
121111
let init_kind = get_init_kind(rest, dcx);
122112
let zeroable_check = match init_kind {
@@ -156,9 +146,8 @@ pub(crate) fn expand(
156146
// generics (which need to be present with that syntax).
157147
#path::#get_data()
158148
};
159-
// Ensure that `#data` really is of type `#data` and help with type inference:
160-
let init = ::pin_init::__internal::#data_trait::make_closure::<_, #error>(
161-
#data,
149+
// Help with type inference.
150+
#data.__make_init::<_, #error>(
162151
move |slot| {
163152
#zeroable_check
164153
#this
@@ -167,12 +156,7 @@ pub(crate) fn expand(
167156
// SAFETY: we are the `init!` macro that is allowed to call this.
168157
Ok(unsafe { ::pin_init::__internal::InitOk::new() })
169158
}
170-
);
171-
let init = move |slot| -> ::core::result::Result<(), #error> {
172-
init(slot).map(|__InitOk| ())
173-
};
174-
// SAFETY: TODO
175-
unsafe { ::pin_init::#init_from_closure::<_, #error>(init) }
159+
)
176160
}})
177161
}
178162

internal/src/pin_data.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,26 @@ fn generate_the_pin_data(
451451
}
452452
}
453453

454-
// SAFETY: TODO
455-
unsafe impl #impl_generics ::pin_init::__internal::PinData for __ThePinData #ty_generics
454+
impl #impl_generics __ThePinData #ty_generics
456455
#whr
457456
{
458-
type Datee = #ident #ty_generics;
457+
/// Type inference helper function.
458+
#[inline(always)]
459+
fn __make_init<F, E>(self, f: F) -> impl ::pin_init::PinInit<#ident #ty_generics, E>
460+
where
461+
F: ::core::ops::FnOnce(*mut #ident #ty_generics) ->
462+
::core::result::Result<::pin_init::__internal::InitOk, E>,
463+
{
464+
// SAFETY: The `InitOk` token created by the macro ensures all safety requirements
465+
// are met.
466+
unsafe {
467+
::pin_init::pin_init_from_closure(move |slot| ->
468+
::core::result::Result<(), E> {
469+
f(slot)?;
470+
Ok(())
471+
})
472+
}
473+
}
459474
}
460475
}
461476
}

src/__internal.rs

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -113,61 +113,25 @@ impl InitOk {
113113
///
114114
/// Only the `init` module is allowed to use this trait.
115115
pub unsafe trait HasPinData {
116-
type PinData: PinData;
116+
type PinData;
117117

118118
#[expect(clippy::missing_safety_doc)]
119119
unsafe fn __pin_data() -> Self::PinData;
120120
}
121121

122-
/// Marker trait for pinning data of structs.
123-
///
124-
/// # Safety
125-
///
126-
/// Only the `init` module is allowed to use this trait.
127-
pub unsafe trait PinData: Copy {
128-
type Datee: ?Sized + HasPinData;
129-
130-
/// Type inference helper function.
131-
#[inline(always)]
132-
fn make_closure<F, E>(self, f: F) -> F
133-
where
134-
F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>,
135-
{
136-
f
137-
}
138-
}
139-
140122
/// This trait is automatically implemented for every type. It aims to provide the same type
141123
/// inference help as `HasPinData`.
142124
///
143125
/// # Safety
144126
///
145127
/// Only the `init` module is allowed to use this trait.
146128
pub unsafe trait HasInitData {
147-
type InitData: InitData;
129+
type InitData;
148130

149131
#[expect(clippy::missing_safety_doc)]
150132
unsafe fn __init_data() -> Self::InitData;
151133
}
152134

153-
/// Same function as `PinData`, but for arbitrary data.
154-
///
155-
/// # Safety
156-
///
157-
/// Only the `init` module is allowed to use this trait.
158-
pub unsafe trait InitData: Copy {
159-
type Datee: ?Sized + HasInitData;
160-
161-
/// Type inference helper function.
162-
#[inline(always)]
163-
fn make_closure<F, E>(self, f: F) -> F
164-
where
165-
F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>,
166-
{
167-
f
168-
}
169-
}
170-
171135
pub struct AllData<T: ?Sized>(PhantomInvariant<T>);
172136

173137
impl<T: ?Sized> Clone for AllData<T> {
@@ -178,9 +142,21 @@ impl<T: ?Sized> Clone for AllData<T> {
178142

179143
impl<T: ?Sized> Copy for AllData<T> {}
180144

181-
// SAFETY: TODO.
182-
unsafe impl<T: ?Sized> InitData for AllData<T> {
183-
type Datee = T;
145+
impl<T: ?Sized> AllData<T> {
146+
/// Type inference helper function.
147+
#[inline(always)]
148+
pub fn __make_init<F, E>(self, f: F) -> impl Init<T, E>
149+
where
150+
F: FnOnce(*mut T) -> Result<InitOk, E>,
151+
{
152+
// SAFETY: The `InitOk` token created by the macro ensures all safety requirements are met.
153+
unsafe {
154+
crate::init_from_closure(move |slot| -> Result<(), E> {
155+
f(slot)?;
156+
Ok(())
157+
})
158+
}
159+
}
184160
}
185161

186162
// SAFETY: TODO.

tests/ui/expand/many_generics.expanded.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,16 +178,35 @@ const _: () = {
178178
}
179179
}
180180
}
181-
unsafe impl<
181+
impl<
182182
'a,
183183
'b: 'a,
184184
T: Bar<'b> + ?Sized + 'a,
185185
const SIZE: usize,
186-
> ::pin_init::__internal::PinData for __ThePinData<'a, 'b, T, SIZE>
186+
> __ThePinData<'a, 'b, T, SIZE>
187187
where
188188
T: Bar<'a, 1>,
189189
{
190-
type Datee = Foo<'a, 'b, T, SIZE>;
190+
/// Type inference helper function.
191+
#[inline(always)]
192+
fn __make_init<F, E>(
193+
self,
194+
f: F,
195+
) -> impl ::pin_init::PinInit<Foo<'a, 'b, T, SIZE>, E>
196+
where
197+
F: ::core::ops::FnOnce(
198+
*mut Foo<'a, 'b, T, SIZE>,
199+
) -> ::core::result::Result<::pin_init::__internal::InitOk, E>,
200+
{
201+
unsafe {
202+
::pin_init::pin_init_from_closure(move |
203+
slot,
204+
| -> ::core::result::Result<(), E> {
205+
f(slot)?;
206+
Ok(())
207+
})
208+
}
209+
}
191210
}
192211
#[allow(dead_code)]
193212
struct __Unpin<'__pin, 'a, 'b: 'a, T: Bar<'b> + ?Sized + 'a, const SIZE: usize = 0>

tests/ui/expand/pin-data.expanded.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,24 @@ const _: () = {
108108
}
109109
}
110110
}
111-
unsafe impl ::pin_init::__internal::PinData for __ThePinData {
112-
type Datee = Foo;
111+
impl __ThePinData {
112+
/// Type inference helper function.
113+
#[inline(always)]
114+
fn __make_init<F, E>(self, f: F) -> impl ::pin_init::PinInit<Foo, E>
115+
where
116+
F: ::core::ops::FnOnce(
117+
*mut Foo,
118+
) -> ::core::result::Result<::pin_init::__internal::InitOk, E>,
119+
{
120+
unsafe {
121+
::pin_init::pin_init_from_closure(move |
122+
slot,
123+
| -> ::core::result::Result<(), E> {
124+
f(slot)?;
125+
Ok(())
126+
})
127+
}
128+
}
113129
}
114130
#[allow(dead_code)]
115131
struct __Unpin<'__pin> {

tests/ui/expand/pinned_drop.expanded.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,24 @@ const _: () = {
108108
}
109109
}
110110
}
111-
unsafe impl ::pin_init::__internal::PinData for __ThePinData {
112-
type Datee = Foo;
111+
impl __ThePinData {
112+
/// Type inference helper function.
113+
#[inline(always)]
114+
fn __make_init<F, E>(self, f: F) -> impl ::pin_init::PinInit<Foo, E>
115+
where
116+
F: ::core::ops::FnOnce(
117+
*mut Foo,
118+
) -> ::core::result::Result<::pin_init::__internal::InitOk, E>,
119+
{
120+
unsafe {
121+
::pin_init::pin_init_from_closure(move |
122+
slot,
123+
| -> ::core::result::Result<(), E> {
124+
f(slot)?;
125+
Ok(())
126+
})
127+
}
128+
}
113129
}
114130
#[allow(dead_code)]
115131
struct __Unpin<'__pin> {

tests/ui/expand/simple-init.expanded.rs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,14 @@ fn main() {
66
use ::pin_init::__internal::HasInitData;
77
Foo::__init_data()
88
};
9-
let init = ::pin_init::__internal::InitData::make_closure::<
10-
_,
11-
::core::convert::Infallible,
12-
>(
13-
__data,
14-
move |slot| {
9+
__data
10+
.__make_init::<
11+
_,
12+
::core::convert::Infallible,
13+
>(move |slot| {
1514
#[allow(unreachable_code, clippy::diverging_sub_expression)]
1615
let _ = || unsafe { ::core::ptr::write(slot, Foo {}) };
1716
Ok(unsafe { ::pin_init::__internal::InitOk::new() })
18-
},
19-
);
20-
let init = move |
21-
slot,
22-
| -> ::core::result::Result<(), ::core::convert::Infallible> {
23-
init(slot).map(|__InitOk| ())
24-
};
25-
unsafe { ::pin_init::init_from_closure::<_, ::core::convert::Infallible>(init) }
17+
})
2618
};
2719
}

0 commit comments

Comments
 (0)