This week was an interesting one for me in the realm of “what counts as safe uses of unsafe code”.
The kick-off was this bug report: “ManuallyDrop causes pinning to be unsound?” https://github.com/asajeffrey/josephine/issues/52.
A stripped-down example is at https://play.rust-lang.org/?gist=607e2dfbd51f4062b9dc93d149815695&version=nightly. The idea is that there’s a type
Pin<'a, T>, with a method
pin(&'a self) -> &'a T whose safety relies on the invariant “after calling
pin.pin(), if the memory backing the pin is ever reclaimed, then the pin’s destructor must have been run”.
This invariant was maintained by Rust until
#[allow(unions_with_drop_fields)] was added, and used by
Now, this code is certainly incorrect (in the sense of https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html) with respect to Rust 1.20. The definition of “incorrect” is a contextual one:
P is incorrect if there is a safe context
C such that
C[P] generates UB. The interesting thing is that (AFAIK!) this program was correct prior to Rust 1.20, because the context that I know of that produces UB uses
mem::forget isn’t enough).
The interesting thing is that this came up in the wild, we already knew that theoretically additions to
std could cause programs to become incorrect, but this is an instance of it actually happening.