Skip to content

Commit 0bd4ee7

Browse files
authored
Rollup merge of #90851 - ibraheemdev:downcast-unchecked, r=scottmcm
Add unchecked downcast methods ```rust impl dyn Any (+ Send + Sync) { pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T; pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T; } impl<A: Allocator> Box<dyn Any (+ Send + Sync), A> { pub unsafe fn downcast_unchecked<T: Any>(&self) -> Box<T, A>; } ```
2 parents f99cd40 + 4ec5cdc commit 0bd4ee7

File tree

2 files changed

+275
-36
lines changed

2 files changed

+275
-36
lines changed

library/alloc/src/boxed.rs

Lines changed: 109 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,8 +1518,6 @@ impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
15181518
}
15191519

15201520
impl<A: Allocator> Box<dyn Any, A> {
1521-
#[inline]
1522-
#[stable(feature = "rust1", since = "1.0.0")]
15231521
/// Attempt to downcast the box to a concrete type.
15241522
///
15251523
/// # Examples
@@ -1537,21 +1535,48 @@ impl<A: Allocator> Box<dyn Any, A> {
15371535
/// print_if_string(Box::new(my_string));
15381536
/// print_if_string(Box::new(0i8));
15391537
/// ```
1538+
#[inline]
1539+
#[stable(feature = "rust1", since = "1.0.0")]
15401540
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
1541-
if self.is::<T>() {
1542-
unsafe {
1543-
let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
1544-
Ok(Box::from_raw_in(raw as *mut T, alloc))
1545-
}
1546-
} else {
1547-
Err(self)
1541+
if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
1542+
}
1543+
1544+
/// Downcasts the box to a concrete type.
1545+
///
1546+
/// For a safe alternative see [`downcast`].
1547+
///
1548+
/// # Examples
1549+
///
1550+
/// ```
1551+
/// #![feature(downcast_unchecked)]
1552+
///
1553+
/// use std::any::Any;
1554+
///
1555+
/// let x: Box<dyn Any> = Box::new(1_usize);
1556+
///
1557+
/// unsafe {
1558+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1559+
/// }
1560+
/// ```
1561+
///
1562+
/// # Safety
1563+
///
1564+
/// The contained value must be of type `T`. Calling this method
1565+
/// with the incorrect type is *undefined behavior*.
1566+
///
1567+
/// [`downcast`]: Self::downcast
1568+
#[inline]
1569+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1570+
pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
1571+
debug_assert!(self.is::<T>());
1572+
unsafe {
1573+
let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
1574+
Box::from_raw_in(raw as *mut T, alloc)
15481575
}
15491576
}
15501577
}
15511578

15521579
impl<A: Allocator> Box<dyn Any + Send, A> {
1553-
#[inline]
1554-
#[stable(feature = "rust1", since = "1.0.0")]
15551580
/// Attempt to downcast the box to a concrete type.
15561581
///
15571582
/// # Examples
@@ -1569,21 +1594,48 @@ impl<A: Allocator> Box<dyn Any + Send, A> {
15691594
/// print_if_string(Box::new(my_string));
15701595
/// print_if_string(Box::new(0i8));
15711596
/// ```
1597+
#[inline]
1598+
#[stable(feature = "rust1", since = "1.0.0")]
15721599
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
1573-
if self.is::<T>() {
1574-
unsafe {
1575-
let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
1576-
Ok(Box::from_raw_in(raw as *mut T, alloc))
1577-
}
1578-
} else {
1579-
Err(self)
1600+
if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
1601+
}
1602+
1603+
/// Downcasts the box to a concrete type.
1604+
///
1605+
/// For a safe alternative see [`downcast`].
1606+
///
1607+
/// # Examples
1608+
///
1609+
/// ```
1610+
/// #![feature(downcast_unchecked)]
1611+
///
1612+
/// use std::any::Any;
1613+
///
1614+
/// let x: Box<dyn Any + Send> = Box::new(1_usize);
1615+
///
1616+
/// unsafe {
1617+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1618+
/// }
1619+
/// ```
1620+
///
1621+
/// # Safety
1622+
///
1623+
/// The contained value must be of type `T`. Calling this method
1624+
/// with the incorrect type is *undefined behavior*.
1625+
///
1626+
/// [`downcast`]: Self::downcast
1627+
#[inline]
1628+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1629+
pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
1630+
debug_assert!(self.is::<T>());
1631+
unsafe {
1632+
let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
1633+
Box::from_raw_in(raw as *mut T, alloc)
15801634
}
15811635
}
15821636
}
15831637

15841638
impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
1585-
#[inline]
1586-
#[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
15871639
/// Attempt to downcast the box to a concrete type.
15881640
///
15891641
/// # Examples
@@ -1601,15 +1653,44 @@ impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
16011653
/// print_if_string(Box::new(my_string));
16021654
/// print_if_string(Box::new(0i8));
16031655
/// ```
1656+
#[inline]
1657+
#[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
16041658
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
1605-
if self.is::<T>() {
1606-
unsafe {
1607-
let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
1608-
Box::into_raw_with_allocator(self);
1609-
Ok(Box::from_raw_in(raw as *mut T, alloc))
1610-
}
1611-
} else {
1612-
Err(self)
1659+
if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
1660+
}
1661+
1662+
/// Downcasts the box to a concrete type.
1663+
///
1664+
/// For a safe alternative see [`downcast`].
1665+
///
1666+
/// # Examples
1667+
///
1668+
/// ```
1669+
/// #![feature(downcast_unchecked)]
1670+
///
1671+
/// use std::any::Any;
1672+
///
1673+
/// let x: Box<dyn Any + Send + Sync> = Box::new(1_usize);
1674+
///
1675+
/// unsafe {
1676+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1677+
/// }
1678+
/// ```
1679+
///
1680+
/// # Safety
1681+
///
1682+
/// The contained value must be of type `T`. Calling this method
1683+
/// with the incorrect type is *undefined behavior*.
1684+
///
1685+
/// [`downcast`]: Self::downcast
1686+
#[inline]
1687+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1688+
pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
1689+
debug_assert!(self.is::<T>());
1690+
unsafe {
1691+
let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
1692+
Box::into_raw_with_allocator(self);
1693+
Box::from_raw_in(raw as *mut T, alloc)
16131694
}
16141695
}
16151696
}

0 commit comments

Comments
 (0)