Is there any guarantee in Rust that lifetime parameters won't change the layout of a type? For example, is the following guaranteed to be okay as long as we ensure that the result doesn't outlive 'a?
// The caller must ensure that the result doesn't outlive 'a.
unsafe fn erase_future_lifetime<'a>(
b: Box<dyn Future<Output = ()> + 'a>,
) -> Box<dyn Future<Output = ()>> {
let raw: *mut (dyn Future<Output = ()> + 'a) = Box::into_raw(b);
let raw2 = raw as *mut (dyn Future<Output = ()> + 'static);
unsafe { Box::from_raw(raw2) }
}
My understanding is that lifetime parameters are only used by the borrow checker at compile time and have no effect on the generated code, so it seems like this should be fine. Is that correct, and is it guaranteed anywhere?
The answer is almost, but not quite.
Let's start with the current state of things: lifetimes are erased in codegen, and therefore they cannot affect layout.
In fact, specialization was (and still is) blocked over that, and nobody proposes the "solution" to make codegen lifetime-aware, because it's not practical.
Proposed memory models of Rust (Stacked Borrows and Tree Borrows) don't know of lifetimes at all.
However, there is no normative statement that states that lifetimes are guaranteed to not affect layout.
Practically, however, a lot of unsafe code relies on that assumption, so it's very, very unlikely to break. I'd consider it safe to rely on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With