diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 70cd46dcfa2b4..3086886a9d769 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -59,6 +59,10 @@ pub trait AnyRefExt<'a> { /// Returns some reference to the boxed value if it is of type `T`, or /// `None` if it isn't. fn as_ref(self) -> Option<&'a T>; + + /// Returns a reference to the boxed value which must be of type `T`. + /// This is as dangerous as `transmute`; you should almost always use `as_ref` instead. + unsafe fn as_ref_unchecked(self) -> &'a T; } impl<'a> AnyRefExt<'a> for &'a Any { @@ -77,41 +81,52 @@ impl<'a> AnyRefExt<'a> for &'a Any { #[inline] fn as_ref(self) -> Option<&'a T> { if self.is::() { - unsafe { - // Get the raw representation of the trait object - let to: TraitObject = transmute_copy(&self); - - // Extract the data pointer - Some(transmute(to.data)) - } + Some(unsafe { self.as_ref_unchecked() }) } else { None } } + + #[inline] + unsafe fn as_ref_unchecked(self) -> &'a T { + // Get the raw representation of the trait object + let to: TraitObject = transmute_copy(&self); + + // Extract the data pointer + transmute(to.data) + } } /// Extension methods for a mutable referenced `Any` trait object pub trait AnyMutRefExt<'a> { /// Returns some mutable reference to the boxed value if it is of type `T`, or /// `None` if it isn't. + #[inline] fn as_mut(self) -> Option<&'a mut T>; + + /// Returns a mutable reference to the boxed value which must be of type `T`. + /// This is as dangerous as `transmute`; you should almost always use `as_mut` instead. + unsafe fn as_mut_unchecked(self) -> &'a mut T; } impl<'a> AnyMutRefExt<'a> for &'a mut Any { #[inline] fn as_mut(self) -> Option<&'a mut T> { if self.is::() { - unsafe { - // Get the raw representation of the trait object - let to: TraitObject = transmute_copy(&self); - - // Extract the data pointer - Some(transmute(to.data)) - } + Some(unsafe { self.as_mut_unchecked() }) } else { None } } + + #[inline] + unsafe fn as_mut_unchecked(self) -> &'a mut T { + // Get the raw representation of the trait object + let to: TraitObject = transmute_copy(&self); + + // Extract the data pointer + transmute(to.data) + } } #[cfg(test)] diff --git a/src/libstd/owned.rs b/src/libstd/owned.rs index 3af12c5154c29..43dd84fc26510 100644 --- a/src/libstd/owned.rs +++ b/src/libstd/owned.rs @@ -77,25 +77,31 @@ pub trait AnyOwnExt { /// Returns the boxed value if it is of type `T`, or /// `Err(Self)` if it isn't. fn move(self) -> Result, Self>; + + /// Returns the boxed value which must be of type `T`. + /// This is as dangerous as `transmute`; you should almost always use `move` instead. + unsafe fn move_unchecked(self) -> Box; } impl AnyOwnExt for Box { #[inline] fn move(self) -> Result, Box> { if self.is::() { - unsafe { - // Get the raw representation of the trait object - let to: TraitObject = - *mem::transmute::<&Box, &TraitObject>(&self); - - // Prevent destructor on self being run - intrinsics::forget(self); - - // Extract the data pointer - Ok(mem::transmute(to.data)) - } + Ok(unsafe { self.move_unchecked() }) } else { Err(self) } } + + #[inline] + unsafe fn move_unchecked(self) -> Box { + // Get the raw representation of the trait object + let to: TraitObject = *mem::transmute::<&Box, &TraitObject>(&self); + + // Prevent destructor on self being run + intrinsics::forget(self); + + // Extract the data pointer + mem::transmute(to.data) + } }