Skip to content

Commit 1ac5440

Browse files
committed
add {Arc, Rc}::downcast_unchecked
1 parent 4b043fa commit 1ac5440

File tree

2 files changed

+80
-5
lines changed

2 files changed

+80
-5
lines changed

Diff for: library/alloc/src/rc.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -1241,8 +1241,6 @@ impl<T: Clone> Rc<T> {
12411241
}
12421242

12431243
impl Rc<dyn Any> {
1244-
#[inline]
1245-
#[stable(feature = "rc_downcast", since = "1.29.0")]
12461244
/// Attempt to downcast the `Rc<dyn Any>` to a concrete type.
12471245
///
12481246
/// # Examples
@@ -1261,6 +1259,8 @@ impl Rc<dyn Any> {
12611259
/// print_if_string(Rc::new(my_string));
12621260
/// print_if_string(Rc::new(0i8));
12631261
/// ```
1262+
#[inline]
1263+
#[stable(feature = "rc_downcast", since = "1.29.0")]
12641264
pub fn downcast<T: Any>(self) -> Result<Rc<T>, Rc<dyn Any>> {
12651265
if (*self).is::<T>() {
12661266
unsafe {
@@ -1272,6 +1272,42 @@ impl Rc<dyn Any> {
12721272
Err(self)
12731273
}
12741274
}
1275+
1276+
/// Downcasts the `Rc<dyn Any>` to a concrete type.
1277+
///
1278+
/// For a safe alternative see [`downcast`].
1279+
///
1280+
/// # Examples
1281+
///
1282+
/// ```
1283+
/// #![feature(downcast_unchecked)]
1284+
///
1285+
/// use std::any::Any;
1286+
/// use std::rc::Rc;
1287+
///
1288+
/// let x: Rc<dyn Any> = Rc::new(1_usize);
1289+
///
1290+
/// unsafe {
1291+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1292+
/// }
1293+
/// ```
1294+
///
1295+
/// # Safety
1296+
///
1297+
/// The contained value must be of type `T`. Calling this method
1298+
/// with the incorrect type is *undefined behavior*.
1299+
///
1300+
///
1301+
/// [`downcast`]: Self::downcast
1302+
#[inline]
1303+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1304+
pub unsafe fn downcast_unchecked<T: Any>(self) -> Rc<T> {
1305+
unsafe {
1306+
let ptr = self.ptr.cast::<RcBox<T>>();
1307+
mem::forget(self);
1308+
Rc::from_inner(ptr)
1309+
}
1310+
}
12751311
}
12761312

12771313
impl<T: ?Sized> Rc<T> {

Diff for: library/alloc/src/sync.rs

+42-3
Original file line numberDiff line numberDiff line change
@@ -1691,8 +1691,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
16911691
}
16921692

16931693
impl Arc<dyn Any + Send + Sync> {
1694-
#[inline]
1695-
#[stable(feature = "rc_downcast", since = "1.29.0")]
16961694
/// Attempt to downcast the `Arc<dyn Any + Send + Sync>` to a concrete type.
16971695
///
16981696
/// # Examples
@@ -1711,9 +1709,11 @@ impl Arc<dyn Any + Send + Sync> {
17111709
/// print_if_string(Arc::new(my_string));
17121710
/// print_if_string(Arc::new(0i8));
17131711
/// ```
1712+
#[inline]
1713+
#[stable(feature = "rc_downcast", since = "1.29.0")]
17141714
pub fn downcast<T>(self) -> Result<Arc<T>, Self>
17151715
where
1716-
T: Any + Send + Sync + 'static,
1716+
T: Any + Send + Sync,
17171717
{
17181718
if (*self).is::<T>() {
17191719
unsafe {
@@ -1725,6 +1725,45 @@ impl Arc<dyn Any + Send + Sync> {
17251725
Err(self)
17261726
}
17271727
}
1728+
1729+
/// Downcasts the `Arc<dyn Any + Send + Sync>` to a concrete type.
1730+
///
1731+
/// For a safe alternative see [`downcast`].
1732+
///
1733+
/// # Examples
1734+
///
1735+
/// ```
1736+
/// #![feature(downcast_unchecked)]
1737+
///
1738+
/// use std::any::Any;
1739+
/// use std::sync::Arc;
1740+
///
1741+
/// let x: Arc<dyn Any + Send + Sync> = Arc::new(1_usize);
1742+
///
1743+
/// unsafe {
1744+
/// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
1745+
/// }
1746+
/// ```
1747+
///
1748+
/// # Safety
1749+
///
1750+
/// The contained value must be of type `T`. Calling this method
1751+
/// with the incorrect type is *undefined behavior*.
1752+
///
1753+
///
1754+
/// [`downcast`]: Self::downcast
1755+
#[inline]
1756+
#[unstable(feature = "downcast_unchecked", issue = "90850")]
1757+
pub unsafe fn downcast_unchecked<T>(self) -> Arc<T>
1758+
where
1759+
T: Any + Send + Sync,
1760+
{
1761+
unsafe {
1762+
let ptr = self.ptr.cast::<ArcInner<T>>();
1763+
mem::forget(self);
1764+
Arc::from_inner(ptr)
1765+
}
1766+
}
17281767
}
17291768

17301769
impl<T> Weak<T> {

0 commit comments

Comments
 (0)