Expand description
&out _
references in stable Rust!
An Out<'a, T>
(&out T
) is a write-only reference.
Its name is inspired by out
parameters from various languages.
It functions like &'a mut MaybeUninit<T>
, except:
- It can be safely constructed from a
&mut T
, since its API forbids writingMaybeUninit::uninit()
.- To avoid accidental memory leaks,
T
must be eitherCopy
or wrapped inManuallyDrop
.
- To avoid accidental memory leaks,
- It supports
Out<[T]>
, whereasMaybeUninit<[T]>
is currently invalid and must be written as[MaybeUninit<T>]
.
Much like &mut MaybeUninit
, you can safely write
to an Out
and get a &mut T
back - also without running any drop glue.
Since it’s proven to be initialized, you can read and write through that reference
without issue.
Interior Mutability
The whole design of Out
references is to forbid any non-unsafe API
that would allow writing MaybeUninit::uninit()
garbage into the
pointee. So, for instance, this crate does not offer any API like:
use ::core::{cell::Cell, mem::MaybeUninit};
// /!\ This is UNSOUND when combined with the `::uninit` crate!
fn swap_mb_uninit_and_cell<T> (
p: &'_ MaybeUninit<Cell<T>>,
) -> &'_ Cell<MaybeUninit<T>>
{
unsafe {
// Safety: both `Cell` and `MaybeUninit` are `#[repr(transparent)]`
::core::mem::transmute(p)
}
}
Indeed, if both such non-unsafe
API and the uninit
crate were
present, then one could trigger UB with:
let mut x = [Cell::new(42)];
let at_mb_uninit_cell: &'_ MaybeUninit<Cell<u8>> =
&x.as_out().as_ref_uninit()[0]
;
swap_mb_uninit_and_cell(at_mb_uninit_cell)
.set(MaybeUninit::uninit()) // UB!
;
The author of the crate believes that such UB is the responsibility of
the one who defined swap_mb_uninit_and_cell
, and that in general that
function is unsound: MaybeUninit
-ness and interior mutability do
not commute!
- the
Safety
annotation in the given example only justifies that it is not breaking any layout-based validity invariants, but it is actually impossible to semantically prove that it is safe for these properties to commute.
If you are strongly convinced of the opposite, please file an issue (if there isn’t already one: since this question is not that clear the author is very likely to create an issue themself).
Modules
&out [_]
slice iteration logic.
Structs
- A write-only reference to a maybe-uninitialized
T