Description
This is the tracking issue for the breaking change made in #136776 The goal of this page is describe why this change was made and how you can fix code that is affected by it. It also provides a place to ask questions or register a complaint if you feel the change should not be made.
What is the warning for?
As part of stabilizing the arbitrary_self_types
and derive_coerce_pointee
we needed to change what raw pointer casts are legal. Specifically, casting *const dyn Trait + 'a
to *const dyn Trait + 'b
where it is not able to be proven that 'a
outlives 'b
has become an error.
Why was this change made?
Casting the lifetime bound on trait objects can invalidate the VTable for the trait object allowing for dispatching to methods that should not be callable. When a trait method has a where Self: 'a
bound, casting the lifetime bound on a trait object may cause the method to go from uncallable to callable.
Example
#![forbid(unsafe_code)]
#![feature(arbitrary_self_types, derive_coerce_pointee)]
use std::any::TypeId;
use std::marker::{CoercePointee, PhantomData};
#[derive(CoercePointee)]
#[repr(transparent)]
struct SelfPtr<T: ?Sized>(*const T);
impl<T: ?Sized> std::ops::Deref for SelfPtr<T> {
type Target = T;
fn deref(&self) -> &T {
panic!("please don't call me, I just want the `Receiver` impl!");
}
}
trait GetTypeId {
fn get_type_id(self: SelfPtr<Self>) -> TypeId
where
Self: 'static;
}
impl<T: ?Sized> GetTypeId for PhantomData<T> {
fn get_type_id(self: SelfPtr<Self>) -> TypeId
where
Self: 'static,
{
TypeId::of::<T>()
}
}
// no `T: 'static` bound necessary
fn type_id_of<T: ?Sized>() -> TypeId {
let ptr = SelfPtr(
// This line no longer compiles
&PhantomData::<T> as *const (dyn GetTypeId + '_) as *const (dyn GetTypeId + 'static),
);
ptr.get_type_id()
}
Migration
Existing code can be trivially migrated by converting the offending raw pointer cast to a lifetime affecting transmute. See metrics-rs/metrics#564 as an example of how such a migration can be accomplished. It's advised to only do so if actually sure that extending the lifetime of the trait object is sound.