Skip to content

Commit 5861251

Browse files
committed
change blanket impls for [Pin]Init and add one for Result<T, E>
Remove the error from the blanket implementations `impl<T, E> Init<T, E> for T` (and also for `PinInit`). Add implementations for `Result<T, E>`. This allows one to easily construct (un)conditional failing initializers. It also improves the compatibility with APIs that do not use pin-init, because users can supply a `Result<T, E>` to a function taking an `impl PinInit<T, E>`. Suggested-by: Alice Ryhl <[email protected]> Signed-off-by: Benno Lossin <[email protected]>
1 parent df925b2 commit 5861251

File tree

4 files changed

+33
-6
lines changed

4 files changed

+33
-6
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- `MaybeZeroable` derive macro to try to derive `Zeroable`, but not error if not all fields
1414
implement it.
1515
- `unsafe fn cast_[pin_]init()` functions to unsafely change the initialized type of an initializer
16+
- `impl<T, E> [Pin]Init<T, E> for Result<T, E>`, so results are now (pin-)initializers
1617

1718
### Changed
1819

1920
- `InPlaceInit` now only exists when the `alloc` or `std` features are enabled
2021
- added support for visibility in `Zeroable` derive macro
2122
- added support for `union`s in `Zeroable` derive macro
2223
- renamed the crate from `pinned-init` to `pin-init` and `pinned-init-macro` to `pin-init-internal`
24+
- blanket impls of `Init` and `PinInit` from `impl<T, E> [Pin]Init<T, E> for T` to
25+
`impl<T> [Pin]Init<T> for T`
2326

2427
### Fixed
2528

src/lib.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,8 +1391,8 @@ where
13911391
}
13921392

13931393
// SAFETY: the `__init` function always returns `Ok(())` and initializes every field of `slot`.
1394-
unsafe impl<T, E> Init<T, E> for T {
1395-
unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
1394+
unsafe impl<T> Init<T> for T {
1395+
unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> {
13961396
// SAFETY: `slot` is valid for writes by the safety requirements of this function.
13971397
unsafe { slot.write(self) };
13981398
Ok(())
@@ -1401,14 +1401,36 @@ unsafe impl<T, E> Init<T, E> for T {
14011401

14021402
// SAFETY: the `__pinned_init` function always returns `Ok(())` and initializes every field of
14031403
// `slot`. Additionally, all pinning invariants of `T` are upheld.
1404-
unsafe impl<T, E> PinInit<T, E> for T {
1405-
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
1404+
unsafe impl<T> PinInit<T> for T {
1405+
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible> {
14061406
// SAFETY: `slot` is valid for writes by the safety requirements of this function.
14071407
unsafe { slot.write(self) };
14081408
Ok(())
14091409
}
14101410
}
14111411

1412+
// SAFETY: when the `__init` function returns with
1413+
// - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld.
1414+
// - `Err(err)`, slot was not written to.
1415+
unsafe impl<T, E> Init<T, E> for Result<T, E> {
1416+
unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
1417+
// SAFETY: `slot` is valid for writes by the safety requirements of this function.
1418+
unsafe { slot.write(self?) };
1419+
Ok(())
1420+
}
1421+
}
1422+
1423+
// SAFETY: when the `__pinned_init` function returns with
1424+
// - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld.
1425+
// - `Err(err)`, slot was not written to.
1426+
unsafe impl<T, E> PinInit<T, E> for Result<T, E> {
1427+
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
1428+
// SAFETY: `slot` is valid for writes by the safety requirements of this function.
1429+
unsafe { slot.write(self?) };
1430+
Ok(())
1431+
}
1432+
}
1433+
14121434
/// Smart pointer containing uninitialized memory and that can write a value.
14131435
pub trait InPlaceWrite<T> {
14141436
/// The type `Self` turns into when the contents are initialized.

tests/ui/compile-fail/init/invalid_init.stderr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ error[E0277]: the trait bound `impl pin_init::PinInit<Bar>: Init<Bar>` is not sa
1010
| |______the trait `Init<Bar>` is not implemented for `impl pin_init::PinInit<Bar>`
1111
| required by a bound introduced by this call
1212
|
13-
= help: the trait `Init<T, E>` is implemented for `ChainInit<I, F, T, E>`
13+
= help: the following other types implement trait `Init<T, E>`:
14+
ChainInit<I, F, T, E>
15+
Result<T, E>
1416
= 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)

tests/ui/compile-fail/pin_data/missing_pin.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ error[E0277]: the trait bound `impl PinInit<usize>: Init<usize, _>` is not satis
88
| |__________^ the trait `Init<usize, _>` is not implemented for `impl PinInit<usize>`
99
|
1010
= help: the trait `Init<usize, _>` is not implemented for `impl PinInit<usize>`
11-
but trait `Init<impl PinInit<usize>, _>` is implemented for it
11+
but trait `Init<impl PinInit<usize>, Infallible>` is implemented for it
1212
= help: for that trait implementation, expected `impl PinInit<usize>`, found `usize`
1313
note: required by a bound in `__ThePinData::a`
1414
--> tests/ui/compile-fail/pin_data/missing_pin.rs:4:1

0 commit comments

Comments
 (0)