mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-29 19:47:38 +00:00
add unchecked downcast methods
This commit is contained in:
parent
e90c5fbbc5
commit
29403eeef0
@ -1482,8 +1482,6 @@ impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Allocator> Box<dyn Any, A> {
|
impl<A: Allocator> Box<dyn Any, A> {
|
||||||
#[inline]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
/// Attempt to downcast the box to a concrete type.
|
/// Attempt to downcast the box to a concrete type.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -1501,21 +1499,46 @@ impl<A: Allocator> Box<dyn Any, A> {
|
|||||||
/// print_if_string(Box::new(my_string));
|
/// print_if_string(Box::new(my_string));
|
||||||
/// print_if_string(Box::new(0i8));
|
/// 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> {
|
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
|
||||||
if self.is::<T>() {
|
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 {
|
unsafe {
|
||||||
let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
|
let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
|
||||||
Ok(Box::from_raw_in(raw as *mut T, alloc))
|
Box::from_raw_in(raw as *mut T, alloc)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Allocator> Box<dyn Any + Send, A> {
|
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.
|
/// Attempt to downcast the box to a concrete type.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # 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(my_string));
|
||||||
/// print_if_string(Box::new(0i8));
|
/// 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> {
|
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
|
||||||
if self.is::<T>() {
|
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 {
|
unsafe {
|
||||||
let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
|
let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
|
||||||
Ok(Box::from_raw_in(raw as *mut T, alloc))
|
Box::from_raw_in(raw as *mut T, alloc)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
|
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.
|
/// Attempt to downcast the box to a concrete type.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # 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(my_string));
|
||||||
/// print_if_string(Box::new(0i8));
|
/// 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> {
|
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
|
||||||
if self.is::<T>() {
|
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 {
|
unsafe {
|
||||||
let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
|
let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
|
||||||
Box::into_raw_with_allocator(self);
|
Box::into_raw_with_allocator(self);
|
||||||
Ok(Box::from_raw_in(raw as *mut T, alloc))
|
Box::from_raw_in(raw as *mut T, alloc)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ impl fmt::Debug for dyn Any + Send + Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl dyn Any {
|
impl dyn Any {
|
||||||
/// Returns `true` if the boxed type is the same as `T`.
|
/// Returns `true` if the inner type is the same as `T`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -195,7 +195,7 @@ impl dyn Any {
|
|||||||
t == concrete
|
t == concrete
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns some reference to the boxed value if it is of type `T`, or
|
/// Returns some reference to the inner value if it is of type `T`, or
|
||||||
/// `None` if it isn't.
|
/// `None` if it isn't.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -221,13 +221,13 @@ impl dyn Any {
|
|||||||
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
|
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
|
||||||
// that check for memory safety because we have implemented Any for all types; no other
|
// that check for memory safety because we have implemented Any for all types; no other
|
||||||
// impls can exist as they would conflict with our impl.
|
// impls can exist as they would conflict with our impl.
|
||||||
unsafe { Some(&*(self as *const dyn Any as *const T)) }
|
unsafe { Some(self.downcast_ref_unchecked()) }
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns some mutable reference to the boxed value if it is of type `T`, or
|
/// Returns some mutable reference to the inner value if it is of type `T`, or
|
||||||
/// `None` if it isn't.
|
/// `None` if it isn't.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -257,15 +257,77 @@ impl dyn Any {
|
|||||||
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
|
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
|
||||||
// that check for memory safety because we have implemented Any for all types; no other
|
// that check for memory safety because we have implemented Any for all types; no other
|
||||||
// impls can exist as they would conflict with our impl.
|
// impls can exist as they would conflict with our impl.
|
||||||
unsafe { Some(&mut *(self as *mut dyn Any as *mut T)) }
|
unsafe { Some(self.downcast_mut_unchecked()) }
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the inner value as type `dyn T`.
|
||||||
|
///
|
||||||
|
/// For a safe alternative see [`downcast_ref`].
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(downcast_unchecked)]
|
||||||
|
///
|
||||||
|
/// use std::any::Any;
|
||||||
|
///
|
||||||
|
/// let x: Box<dyn Any> = Box::new(1_usize);
|
||||||
|
///
|
||||||
|
/// unsafe {
|
||||||
|
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The contained value must be of type `T`. Calling this method
|
||||||
|
/// with the incorrect type is *undefined behavior*.
|
||||||
|
#[unstable(feature = "downcast_unchecked", issue = "none")]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
|
||||||
|
debug_assert!(self.is::<T>());
|
||||||
|
// SAFETY: caller guarantees that T is the correct type
|
||||||
|
unsafe { &*(self as *const dyn Any as *const T) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the inner value as type `dyn T`.
|
||||||
|
///
|
||||||
|
/// For a safe alternative see [`downcast_mut`].
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(downcast_unchecked)]
|
||||||
|
///
|
||||||
|
/// use std::any::Any;
|
||||||
|
///
|
||||||
|
/// let mut x: Box<dyn Any> = Box::new(1_usize);
|
||||||
|
///
|
||||||
|
/// unsafe {
|
||||||
|
/// *x.downcast_mut_unchecked::<usize>() += 1;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The contained value must be of type `T`. Calling this method
|
||||||
|
/// with the incorrect type is *undefined behavior*.
|
||||||
|
#[unstable(feature = "downcast_unchecked", issue = "none")]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
|
||||||
|
debug_assert!(self.is::<T>());
|
||||||
|
// SAFETY: caller guarantees that T is the correct type
|
||||||
|
unsafe { &mut *(self as *mut dyn Any as *mut T) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl dyn Any + Send {
|
impl dyn Any + Send {
|
||||||
/// Forwards to the method defined on the type `Any`.
|
/// Forwards to the method defined on the type `dyn Any`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -289,7 +351,7 @@ impl dyn Any + Send {
|
|||||||
<dyn Any>::is::<T>(self)
|
<dyn Any>::is::<T>(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forwards to the method defined on the type `Any`.
|
/// Forwards to the method defined on the type `dyn Any`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -313,7 +375,7 @@ impl dyn Any + Send {
|
|||||||
<dyn Any>::downcast_ref::<T>(self)
|
<dyn Any>::downcast_ref::<T>(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forwards to the method defined on the type `Any`.
|
/// Forwards to the method defined on the type `dyn Any`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -340,6 +402,60 @@ impl dyn Any + Send {
|
|||||||
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
||||||
<dyn Any>::downcast_mut::<T>(self)
|
<dyn Any>::downcast_mut::<T>(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Forwards to the method defined on the type `dyn Any`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(downcast_unchecked)]
|
||||||
|
///
|
||||||
|
/// use std::any::Any;
|
||||||
|
///
|
||||||
|
/// let x: Box<dyn Any> = Box::new(1_usize);
|
||||||
|
///
|
||||||
|
/// unsafe {
|
||||||
|
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Same as the method on the type `dyn Any`.
|
||||||
|
#[unstable(feature = "downcast_unchecked", issue = "none")]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
|
||||||
|
// SAFETY: guaranteed by caller
|
||||||
|
unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Forwards to the method defined on the type `dyn Any`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(downcast_unchecked)]
|
||||||
|
///
|
||||||
|
/// use std::any::Any;
|
||||||
|
///
|
||||||
|
/// let mut x: Box<dyn Any> = Box::new(1_usize);
|
||||||
|
///
|
||||||
|
/// unsafe {
|
||||||
|
/// *x.downcast_mut_unchecked::<usize>() += 1;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Same as the method on the type `dyn Any`.
|
||||||
|
#[unstable(feature = "downcast_unchecked", issue = "none")]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
|
||||||
|
// SAFETY: guaranteed by caller
|
||||||
|
unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl dyn Any + Send + Sync {
|
impl dyn Any + Send + Sync {
|
||||||
@ -418,6 +534,52 @@ impl dyn Any + Send + Sync {
|
|||||||
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
||||||
<dyn Any>::downcast_mut::<T>(self)
|
<dyn Any>::downcast_mut::<T>(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Forwards to the method defined on the type `Any`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(downcast_unchecked)]
|
||||||
|
///
|
||||||
|
/// use std::any::Any;
|
||||||
|
///
|
||||||
|
/// let x: Box<dyn Any> = Box::new(1_usize);
|
||||||
|
///
|
||||||
|
/// unsafe {
|
||||||
|
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "downcast_unchecked", issue = "none")]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
|
||||||
|
// SAFETY: guaranteed by caller
|
||||||
|
unsafe { <dyn Any>::downcast_ref_unchecked::<T>(self) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Forwards to the method defined on the type `Any`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(downcast_unchecked)]
|
||||||
|
///
|
||||||
|
/// use std::any::Any;
|
||||||
|
///
|
||||||
|
/// let mut x: Box<dyn Any> = Box::new(1_usize);
|
||||||
|
///
|
||||||
|
/// unsafe {
|
||||||
|
/// *x.downcast_mut_unchecked::<usize>() += 1;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "downcast_unchecked", issue = "none")]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
|
||||||
|
// SAFETY: guaranteed by caller
|
||||||
|
unsafe { <dyn Any>::downcast_mut_unchecked::<T>(self) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user