diff --git a/CHANGELOG.md b/CHANGELOG.md index 2145b280..45ba72e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `MaybeZeroable` derive macro to try to derive `Zeroable`, but not error if not all fields implement it. - `unsafe fn cast_[pin_]init()` functions to unsafely change the initialized type of an initializer +- `impl [Pin]Init for Result`, so results are now (pin-)initializers ### Changed @@ -20,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - added support for visibility in `Zeroable` derive macro - added support for `union`s in `Zeroable` derive macro - renamed the crate from `pinned-init` to `pin-init` and `pinned-init-macro` to `pin-init-internal` +- blanket impls of `Init` and `PinInit` from `impl [Pin]Init for T` to + `impl [Pin]Init for T` ### Fixed diff --git a/src/lib.rs b/src/lib.rs index 9ab34036..f4e03449 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1390,20 +1390,44 @@ where unsafe { pin_init_from_closure(init) } } -// SAFETY: Every type can be initialized by-value. -unsafe impl Init for T { - unsafe fn __init(self, slot: *mut T) -> Result<(), E> { - // SAFETY: TODO. +// SAFETY: the `__init` function always returns `Ok(())` and initializes every field of `slot`. +unsafe impl Init for T { + unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> { + // SAFETY: `slot` is valid for writes by the safety requirements of this function. unsafe { slot.write(self) }; Ok(()) } } -// SAFETY: Every type can be initialized by-value. `__pinned_init` calls `__init`. -unsafe impl PinInit for T { +// SAFETY: the `__pinned_init` function always returns `Ok(())` and initializes every field of +// `slot`. Additionally, all pinning invariants of `T` are upheld. +unsafe impl PinInit for T { + unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible> { + // SAFETY: `slot` is valid for writes by the safety requirements of this function. + unsafe { slot.write(self) }; + Ok(()) + } +} + +// SAFETY: when the `__init` function returns with +// - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld. +// - `Err(err)`, slot was not written to. +unsafe impl Init for Result { + unsafe fn __init(self, slot: *mut T) -> Result<(), E> { + // SAFETY: `slot` is valid for writes by the safety requirements of this function. + unsafe { slot.write(self?) }; + Ok(()) + } +} + +// SAFETY: when the `__pinned_init` function returns with +// - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld. +// - `Err(err)`, slot was not written to. +unsafe impl PinInit for Result { unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { - // SAFETY: TODO. - unsafe { self.__init(slot) } + // SAFETY: `slot` is valid for writes by the safety requirements of this function. + unsafe { slot.write(self?) }; + Ok(()) } } diff --git a/tests/ui/compile-fail/init/invalid_init.stderr b/tests/ui/compile-fail/init/invalid_init.stderr index 7731bc31..b80864de 100644 --- a/tests/ui/compile-fail/init/invalid_init.stderr +++ b/tests/ui/compile-fail/init/invalid_init.stderr @@ -10,5 +10,7 @@ error[E0277]: the trait bound `impl pin_init::PinInit: Init` is not sa | |______the trait `Init` is not implemented for `impl pin_init::PinInit` | required by a bound introduced by this call | - = help: the trait `Init` is implemented for `ChainInit` + = help: the following other types implement trait `Init`: + ChainInit + Result = note: this error originates in the macro `$crate::__init_internal` which comes from the expansion of the macro `init` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/compile-fail/pin_data/missing_pin.stderr b/tests/ui/compile-fail/pin_data/missing_pin.stderr index 5d98a04c..a7b1a587 100644 --- a/tests/ui/compile-fail/pin_data/missing_pin.stderr +++ b/tests/ui/compile-fail/pin_data/missing_pin.stderr @@ -8,7 +8,7 @@ error[E0277]: the trait bound `impl PinInit: Init` is not satis | |__________^ the trait `Init` is not implemented for `impl PinInit` | = help: the trait `Init` is not implemented for `impl PinInit` - but trait `Init, _>` is implemented for it + but trait `Init, Infallible>` is implemented for it = help: for that trait implementation, expected `impl PinInit`, found `usize` note: required by a bound in `__ThePinData::a` --> tests/ui/compile-fail/pin_data/missing_pin.rs:4:1