Description
I spotted this in PyO3: (PyO3/pyo3#536)
if next_idx == 0 {
self.inner
.push_back(unsafe { mem::MaybeUninit::uninit().assume_init() });
}
GitHub search brings up a total of 62 matches even for a fairly restrictive search query: https://github.com/search?q=%22uninit%28%29%3A%3Aassume_init%28%29%22&type=Code
Problem: It seems people are using this as an easy way out of the deprecation warnings for std::mem::uninitialized
, failing to understand the reason why it was deprecated (it is, to my current understanding, universally UB, always!). The correct solution is to use MaybeUninit<T>
where you were formerly using T until the value is known to be initialized. The MaybeUninit<T>
docs even give examples for what are by far the two most common use cases (out pointers and partially-initialized arrays).
Proposal: There should either be a warn-by-default or an error-by-default lint against immediate calls to assume_init()
on MaybeUninit::uninit()
with no other intervening operations.
Possible extension: We can try going a step further and adjust our suggestions based on the type:
- In the case where
T
is uninhabited, we can instead recommend the use ofstd::hint::unreachable_unchecked
. - If
T = [A; N]
, we can specifically recommend that the user constructs a[MaybeUninit<A>; N]
. (as this is often a key piece of the correct solution that the user might not think of on their own, and without it they may simply invent some other way to silence the warning improperly)