Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ jobs:
fi
working-directory: pin-init
- name: Run checkpatch.pl
continue-on-error: true
run: |
if [ "$(git rev-parse HEAD)" = "$(git rev-parse origin/pin-init-next)" ]; then
# when there are no new commits, we can succeed directly
Expand Down
25 changes: 13 additions & 12 deletions internal/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,18 +269,17 @@ fn expand(
},
|(_, err)| Box::new(err),
);
let (has_data_trait, get_data, init_from_closure) = if pinned {
let (get_pin_data, init_from_closure) = if pinned {
(
format_ident!("HasPinData"),
format_ident!("__pin_data"),
Some(
quote_spanned! { path.span().resolved_at(Span::mixed_site()) =>
let data = ::pin_init::__internal::HasPinData::__pin_data(data);
},
),
format_ident!("pin_init_from_closure"),
)
} else {
(
format_ident!("HasInitData"),
format_ident!("__init_data"),
format_ident!("init_from_closure"),
)
(None, format_ident!("init_from_closure"))
};
let init_kind = get_init_kind(rest, dcx);
let zeroable_check = match init_kind {
Expand Down Expand Up @@ -312,13 +311,15 @@ fn expand(
let field_check = make_field_check(&fields, init_kind, &path);
Ok(quote_spanned! { Span::mixed_site() => {
// Get the data about fields from the supplied type.
// SAFETY: TODO
let data = unsafe {
use ::pin_init::__internal::#has_data_trait;
let data = {
use ::pin_init::__internal::HasInitData;
// Can't use `<#path as #has_data_trait>::#get_data`, since the user is able to omit
// generics (which need to be present with that syntax).
#path::#get_data()
#path::__init_data()
};

#get_pin_data

// Ensure that `data` really is of type `data` and help with type inference:
let init = data.__make_closure::<_, #error>(
move |slot| {
Expand Down
2 changes: 1 addition & 1 deletion internal/src/pin_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ fn generate_the_pin_data(
type PinData = __ThePinData #ty_generics;

#[inline]
unsafe fn __pin_data() -> Self::PinData {
fn __pin_data(_: ::pin_init::__internal::InitData<Self>) -> Self::PinData {
__ThePinData { __phantom: ::pin_init::__internal::PhantomInvariant::new() }
}
}
Expand Down
48 changes: 21 additions & 27 deletions src/__internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,39 +81,43 @@ impl InitOk {
///
/// # Safety
///
/// Only the `init` module is allowed to use this trait.
/// `pin-init` relies on the correctness of the helper functions defined on `PinData`.
/// Thus, only the `#[pin_data]` can implement this trait.
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be used with `pin_init!` macro",
note = "did you forget to add `#[pin_data]` attribute to the struct?"
)]
pub unsafe trait HasPinData {
type PinData;

#[expect(clippy::missing_safety_doc)]
unsafe fn __pin_data() -> Self::PinData;
fn __pin_data(_: InitData<Self>) -> Self::PinData;
}

/// This trait is automatically implemented for every type. It aims to provide the same type
/// inference help as `HasPinData`.
/// This trait is automatically implemented for every type.
///
/// # Safety
///
/// Only the `init` module is allowed to use this trait.
pub unsafe trait HasInitData {
type InitData;

#[expect(clippy::missing_safety_doc)]
unsafe fn __init_data() -> Self::InitData;
/// It aims to provide type inference help; `PATH::__init_data()` would be able to retrieve an
/// instance of `InitData<PATH<Generics>>` without having to mention the generics explicitly.
pub trait HasInitData {
#[inline]
fn __init_data() -> InitData<Self> {
InitData(PhantomInvariant::new())
}
}

pub struct AllData<T: ?Sized>(PhantomInvariant<T>);
impl<T: ?Sized> HasInitData for T {}

pub struct InitData<T: ?Sized>(PhantomInvariant<T>);

impl<T: ?Sized> Clone for AllData<T> {
impl<T: ?Sized> Clone for InitData<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}

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

impl<T: ?Sized> AllData<T> {
impl<T: ?Sized> InitData<T> {
/// Type inference helper function.
#[inline(always)]
pub fn __make_closure<F, E>(self, f: F) -> F
Expand All @@ -124,16 +128,6 @@ impl<T: ?Sized> AllData<T> {
}
}

// SAFETY: TODO.
unsafe impl<T: ?Sized> HasInitData for T {
type InitData = AllData<T>;

#[inline]
unsafe fn __init_data() -> Self::InitData {
AllData(PhantomInvariant::new())
}
}

/// Stack initializer helper type. Use [`stack_pin_init`] instead of this primitive.
///
/// # Invariants
Expand Down
11 changes: 10 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,8 @@ macro_rules! assert_pinned {
($ty:ty, $field:ident, $field_ty:ty, inline) => {
// SAFETY: This code is unreachable.
let _ = move |ptr: *mut $ty| unsafe {
let data = <$ty as $crate::__internal::HasPinData>::__pin_data();
let data = <$ty as $crate::__internal::HasInitData>::__init_data();
let data = $crate::__internal::HasPinData::__pin_data(data);
_ = data
.$field(ptr)
.init($crate::__internal::AlwaysFail::<$field_ty>::new());
Expand Down Expand Up @@ -965,6 +966,9 @@ macro_rules! assert_pinned {
#[cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]
#[cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]
#[must_use = "An initializer must be used in order to create its value."]
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be used to initialize `{T}` with error `{E}`"
)]
pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
/// Alias of [`PinInit::__init`].
///
Expand Down Expand Up @@ -1099,6 +1103,11 @@ where
#[cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]
#[cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]
#[must_use = "An initializer must be used in order to create its value."]
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be used to movably initialize `{T}` with error `{E}`",
note = "if your type implements `PinInit` but not `Init`, \
you might be forgetting a `#[pin]` annotation on fields"
)]
pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
/// First initializes the value using `self` then calls the function `f` with the initialized
/// value.
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/compile-fail/init/invalid_init.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0277]: the trait bound `impl pin_init::PinInit<Bar>: Init<Bar, _>` is not satisfied
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(),
Expand All @@ -7,6 +7,7 @@ error[E0277]: the trait bound `impl pin_init::PinInit<Bar>: Init<Bar, _>` is not
| | 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
help: the following other types implement trait `Init<T, E>`
--> src/lib.rs
|
Expand Down
18 changes: 9 additions & 9 deletions tests/ui/compile-fail/init/missing_pin_data.stderr
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error[E0599]: no associated function or constant named `__pin_data` found for struct `Foo` in the current scope
--> tests/ui/compile-fail/init/missing_pin_data.rs:9:9
error[E0277]: `Foo` cannot be used with `pin_init!` macro
--> tests/ui/compile-fail/init/missing_pin_data.rs:9:19
|
3 | struct Foo {
| ---------- associated function or constant `__pin_data` not found for this struct
...
9 | pin_init!(Self { a: 42 })
| ^^^^^^^^^^^^^^^^^^^^^^^^^ associated function or constant not found in `Foo`
| ^^^^ unsatisfied trait bound
|
help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo`
--> tests/ui/compile-fail/init/missing_pin_data.rs:3:1
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `__pin_data`, perhaps you need to implement it:
candidate #1: `pin_init::__internal::HasPinData`
3 | struct Foo {
| ^^^^^^^^^^
= note: did you forget to add `#[pin_data]` attribute to the struct?
= note: this error originates in the macro `pin_init` (in Nightly builds, run with -Z macro-backtrace for more info)
3 changes: 2 additions & 1 deletion tests/ui/compile-fail/pin_data/missing_pin.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0277]: the trait bound `impl PinInit<usize>: Init<usize, _>` is not satisfied
error[E0277]: `impl PinInit<usize>` cannot be used to movably initialize `usize` with error `_`
--> tests/ui/compile-fail/pin_data/missing_pin.rs:12:18
|
12 | a <- a,
Expand All @@ -7,6 +7,7 @@ error[E0277]: the trait bound `impl PinInit<usize>: Init<usize, _>` is not satis
| | the trait `Init<usize, _>` is not implemented for `impl PinInit<usize>`
| 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
help: the trait `Init<usize, _>` is not implemented for `impl PinInit<usize>`
but trait `Init<impl PinInit<usize>, !>` is implemented for it
--> src/lib.rs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0277]: the trait bound `Foo: pin_init::__internal::HasPinData` is not satisfied
error[E0277]: `Foo` cannot be used with `pin_init!` macro
--> tests/ui/compile-fail/pinned_drop/no_pin_data_but_pinned_drop.rs:7:21
|
7 | impl PinnedDrop for Foo {
Expand All @@ -9,6 +9,7 @@ help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo`
|
4 | struct Foo {}
| ^^^^^^^^^^
= note: did you forget to add `#[pin_data]` attribute to the struct?
note: required by a bound in `PinnedDrop`
--> src/lib.rs
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/expand/many_generics.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ const _: () = {
{
type PinData = __ThePinData<'a, 'b, T, SIZE>;
#[inline]
unsafe fn __pin_data() -> Self::PinData {
fn __pin_data(_: ::pin_init::__internal::InitData<Self>) -> Self::PinData {
__ThePinData {
__phantom: ::pin_init::__internal::PhantomInvariant::new(),
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/expand/pin-data.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const _: () = {
unsafe impl ::pin_init::__internal::HasPinData for Foo {
type PinData = __ThePinData;
#[inline]
unsafe fn __pin_data() -> Self::PinData {
fn __pin_data(_: ::pin_init::__internal::InitData<Self>) -> Self::PinData {
__ThePinData {
__phantom: ::pin_init::__internal::PhantomInvariant::new(),
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/expand/pinned_drop.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const _: () = {
unsafe impl ::pin_init::__internal::HasPinData for Foo {
type PinData = __ThePinData;
#[inline]
unsafe fn __pin_data() -> Self::PinData {
fn __pin_data(_: ::pin_init::__internal::InitData<Self>) -> Self::PinData {
__ThePinData {
__phantom: ::pin_init::__internal::PhantomInvariant::new(),
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/expand/simple-init.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use pin_init::*;
struct Foo {}
fn main() {
let _ = {
let data = unsafe {
let data = {
use ::pin_init::__internal::HasInitData;
Foo::__init_data()
};
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/expand/tuple_struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ const _: () = {
for Foo<'a, T, N> {
type PinData = __ThePinData<'a, T, N>;
#[inline]
unsafe fn __pin_data() -> Self::PinData {
fn __pin_data(_: ::pin_init::__internal::InitData<Self>) -> Self::PinData {
__ThePinData {
__phantom: ::pin_init::__internal::PhantomInvariant::new(),
}
Expand Down Expand Up @@ -142,7 +142,7 @@ const _: () = {
fn main() {
let mut first = [1u8, 2, 3];
let _ = {
let data = unsafe {
let data = {
use ::pin_init::__internal::HasInitData;
Foo::__init_data()
};
Expand Down Expand Up @@ -200,7 +200,7 @@ fn main() {
};
let mut second = [4u8, 5, 6];
let _ = {
let data = unsafe {
let data = {
use ::pin_init::__internal::HasInitData;
Foo::__init_data()
};
Expand Down
Loading