diff options
| author | Ibraheem Ahmed <ibrah1440@gmail.com> | 2021-11-12 22:53:26 -0500 |
|---|---|---|
| committer | Ibraheem Ahmed <ibrah1440@gmail.com> | 2021-11-12 22:53:26 -0500 |
| commit | 29403eeef0b175b4a65cc3c7865708ee15d8a7e8 (patch) | |
| tree | 4598446e39380ef73fd490c466bef09ee2b16afd /library/alloc/src | |
| parent | e90c5fbbc5df5c81267747daeb937d4e955ce6ad (diff) | |
| download | rust-29403eeef0b175b4a65cc3c7865708ee15d8a7e8.tar.gz rust-29403eeef0b175b4a65cc3c7865708ee15d8a7e8.zip | |
add unchecked downcast methods
Diffstat (limited to 'library/alloc/src')
| -rw-r--r-- | library/alloc/src/boxed.rs | 131 |
1 files changed, 103 insertions, 28 deletions
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index f6332b072cf..81ac37a306b 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1482,8 +1482,6 @@ impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> { } impl<A: Allocator> Box<dyn Any, A> { - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. /// /// # Examples @@ -1501,21 +1499,46 @@ impl<A: Allocator> Box<dyn Any, A> { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` + #[inline] + #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> { - if self.is::<T>() { - unsafe { - let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); - Ok(Box::from_raw_in(raw as *mut T, alloc)) - } - } else { - Err(self) + if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box<dyn Any> = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::<usize>(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "none")] + pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> { + debug_assert!(self.is::<T>()); + unsafe { + let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) } } } impl<A: Allocator> Box<dyn Any + Send, A> { - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. /// /// # Examples @@ -1533,21 +1556,46 @@ impl<A: Allocator> Box<dyn Any + Send, A> { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` + #[inline] + #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> { - if self.is::<T>() { - unsafe { - let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); - Ok(Box::from_raw_in(raw as *mut T, alloc)) - } - } else { - Err(self) + if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box<dyn Any + Send> = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::<usize>(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "none")] + pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> { + debug_assert!(self.is::<T>()); + unsafe { + let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) } } } impl<A: Allocator> Box<dyn Any + Send + Sync, A> { - #[inline] - #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] /// Attempt to downcast the box to a concrete type. /// /// # Examples @@ -1565,15 +1613,42 @@ impl<A: Allocator> Box<dyn Any + Send + Sync, A> { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` + #[inline] + #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> { - if self.is::<T>() { - unsafe { - let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = - Box::into_raw_with_allocator(self); - Ok(Box::from_raw_in(raw as *mut T, alloc)) - } - } else { - Err(self) + if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box<dyn Any + Send + Sync> = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::<usize>(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "none")] + pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> { + debug_assert!(self.is::<T>()); + unsafe { + let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = + Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) } } } |
