Closed
Description
Now that DST has landed, I've been working on refactoring various library code to take advantage of it. I tried to remove some of the extension traits currently used in core::any
, but ran into a strange error for downcase_mut
that was solved by explicitly reborrowing the receiver:
/// The `Any` trait is implemented by all `'static` types, and can be used for
/// dynamic typing
///
/// Every type with no non-`'static` references implements `Any`, so `Any` can
/// be used as a trait object to emulate the effects dynamic typing.
#[stable]
pub trait Any: AnyPrivate {
/// Returns true if the boxed type is the same as `T`
#[inline]
#[stable]
fn is<T: 'static>(&self) -> bool {
// Get TypeId of the type this function is instantiated with
let t = TypeId::of::<T>();
// Get TypeId of the type in the trait object
let boxed = self.get_type_id();
// Compare both TypeIds on equality
t == boxed
}
/// Returns some reference to the boxed value if it is of type `T`, or
/// `None` if it isn't.
#[inline]
#[unstable = "naming conventions around acquiring references may change"]
fn downcast_ref<T: 'static>(&self) -> Option<&T> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
let to: TraitObject = transmute_copy(&self);
// Extract the data pointer
Some(transmute(to.data))
}
} else {
None
}
}
/// Returns some mutable reference to the boxed value if it is of type `T`, or
/// `None` if it isn't.
#[inline]
#[unstable = "naming conventions around acquiring references may change"]
fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
// The following fails with:
// error: instantiating a type parameter with an incompatible type `&mut Self`,
// which does not fulfill `'static`
// if self.is::<T>() {
// Explicitly reborrowing seems to work:
if (&*self).is::<T>() {
unsafe {
// Get the raw representation of the trait object
let to: TraitObject = transmute_copy(&self);
// Extract the data pointer
Some(transmute(to.data))
}
} else {
None
}
}
/// Returns some reference to the boxed value if it is of type `T`, or
/// `None` if it isn't.
#[deprecated = "this function has been renamed to `downcast_ref`"]
fn as_ref<T: 'static>(&self) -> Option<&T> {
self.downcast_ref::<T>()
}
/// Returns some mutable reference to the boxed value if it is of type `T`, or
/// `None` if it isn't.
#[deprecated = "this function has been renamed to `downcast_mut`"]
fn as_mut<T: 'static>(&mut self) -> Option<&mut T> {
self.downcast_mut::<T>()
}
}
/// An inner trait to ensure that only this module can call `get_type_id()`.
trait AnyPrivate {
/// Get the `TypeId` of `self`
fn get_type_id(&self) -> TypeId;
}
impl<T: 'static> AnyPrivate for T {
fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
}
impl<T: 'static + AnyPrivate> Any for T {}