Skip to content

Commit d51458a

Browse files
committed
Make Arc<T>::deref zero-cost
1 parent 19fb34b commit d51458a

File tree

10 files changed

+636
-1388
lines changed

10 files changed

+636
-1388
lines changed

library/alloc/src/raw_rc/raw_rc.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,16 @@ where
225225
self.weak.into_raw_parts()
226226
}
227227

228+
// `is_unique` only exists on `Arc`, so we need this `#[cfg(not(no_sync))]`. It can be removed
229+
// if `Rc::is_unique` is added.
230+
#[cfg(not(no_sync))]
231+
pub(crate) unsafe fn is_unique<R>(&self) -> bool
232+
where
233+
R: RcOps,
234+
{
235+
unsafe { is_unique::<R>(self.weak.as_ptr().cast()) }
236+
}
237+
228238
#[cfg(not(no_global_oom_handling))]
229239
pub(crate) unsafe fn make_mut<R>(&mut self) -> &mut T
230240
where
@@ -710,6 +720,23 @@ impl<A> RawRc<dyn Any, A> {
710720
}
711721
}
712722

723+
#[cfg(not(no_sync))]
724+
impl<A> RawRc<dyn Any + Send + Sync, A> {
725+
pub(crate) fn downcast<T>(self) -> Result<RawRc<T, A>, Self>
726+
where
727+
T: Any,
728+
{
729+
if self.as_ref().is::<T>() { Ok(unsafe { self.downcast_unchecked() }) } else { Err(self) }
730+
}
731+
732+
pub(crate) unsafe fn downcast_unchecked<T>(self) -> RawRc<T, A>
733+
where
734+
T: Any,
735+
{
736+
unsafe { self.cast() }
737+
}
738+
}
739+
713740
impl<T, A> AsRef<T> for RawRc<T, A>
714741
where
715742
T: ?Sized,

library/alloc/src/raw_rc/raw_weak.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,13 +283,19 @@ where
283283
!ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr())
284284
}
285285

286+
/// Returns the `RefCounts` object inside the reference-counted allocation if `self` is
287+
/// non-dangling.
288+
#[cfg(not(no_sync))]
289+
pub(crate) fn ref_counts(&self) -> Option<&RefCounts> {
290+
(!is_dangling(self.ptr.cast())).then(|| unsafe { self.ref_counts_unchecked() })
291+
}
292+
286293
/// Returns the `RefCounts` object inside the reference-counted allocation, assume `self` is
287294
/// non-dangling.
288295
///
289296
/// # Safety
290297
///
291298
/// `self` is non-dangling.
292-
#[cfg(not(no_global_oom_handling))]
293299
pub(super) unsafe fn ref_counts_unchecked(&self) -> &RefCounts {
294300
unsafe { super::ref_counts_ptr_from_value_ptr(self.ptr.cast()).as_ref() }
295301
}

0 commit comments

Comments
 (0)