-
Notifications
You must be signed in to change notification settings - Fork 13.6k
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
now requires that 'a
outlives 'b
.
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 migrated by replacing the offending raw pointer cast with a 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.