Skip to content

Commit 42e03cc

Browse files
committed
Add ub_checks for downcast_unchecked
Right now debug_assert! is used, which will not trigger in user code. This is likely unacceptable for performance reasons, since the optimizer can not understand virtual Any::type_id() calls. This could potentially be fixed if we apply something like #[ffi_const] to the Any::type_id() function (which would have wierder reaching benefits). This cannot use the assert_unsafe_precondition! macro, because that requires the assertion to work in a const context.
1 parent 040a98a commit 42e03cc

File tree

4 files changed

+21
-5
lines changed

4 files changed

+21
-5
lines changed

library/alloc/src/boxed/convert.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,9 @@ impl<A: Allocator> Box<dyn Any, A> {
392392
#[inline]
393393
#[unstable(feature = "downcast_unchecked", issue = "90850")]
394394
pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
395-
debug_assert!(self.is::<T>());
395+
if core::ub_checks::check_library_ub() {
396+
assert!(self.is::<T>());
397+
}
396398
unsafe {
397399
let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
398400
Box::from_raw_in(raw as *mut T, alloc)
@@ -451,7 +453,9 @@ impl<A: Allocator> Box<dyn Any + Send, A> {
451453
#[inline]
452454
#[unstable(feature = "downcast_unchecked", issue = "90850")]
453455
pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
454-
debug_assert!(self.is::<T>());
456+
if core::ub_checks::check_library_ub() {
457+
assert!(self.is::<T>());
458+
}
455459
unsafe {
456460
let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
457461
Box::from_raw_in(raw as *mut T, alloc)
@@ -510,7 +514,9 @@ impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
510514
#[inline]
511515
#[unstable(feature = "downcast_unchecked", issue = "90850")]
512516
pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
513-
debug_assert!(self.is::<T>());
517+
if core::ub_checks::check_library_ub() {
518+
assert!(self.is::<T>());
519+
}
514520
unsafe {
515521
let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
516522
Box::into_raw_with_allocator(self);

library/alloc/src/rc.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,6 +2042,9 @@ impl<A: Allocator> Rc<dyn Any, A> {
20422042
#[inline]
20432043
#[unstable(feature = "downcast_unchecked", issue = "90850")]
20442044
pub unsafe fn downcast_unchecked<T: Any>(self) -> Rc<T, A> {
2045+
if core::ub_checks::check_library_ub() {
2046+
assert!((*self).is::<T>());
2047+
}
20452048
unsafe {
20462049
let (ptr, alloc) = Rc::into_inner_with_allocator(self);
20472050
Rc::from_inner_in(ptr.cast(), alloc)

library/alloc/src/sync.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2754,6 +2754,9 @@ impl<A: Allocator> Arc<dyn Any + Send + Sync, A> {
27542754
where
27552755
T: Any + Send + Sync,
27562756
{
2757+
if core::ub_checks::check_library_ub() {
2758+
assert!((*self).is::<T>());
2759+
}
27572760
unsafe {
27582761
let (ptr, alloc) = Arc::into_inner_with_allocator(self);
27592762
Arc::from_inner_in(ptr.cast(), alloc)

library/core/src/any.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ impl dyn Any {
292292
#[unstable(feature = "downcast_unchecked", issue = "90850")]
293293
#[inline]
294294
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
295-
debug_assert!(self.is::<T>());
295+
if core::ub_checks::check_library_ub() {
296+
assert!(self.is::<T>());
297+
}
296298
// SAFETY: caller guarantees that T is the correct type
297299
unsafe { &*(self as *const dyn Any as *const T) }
298300
}
@@ -322,7 +324,9 @@ impl dyn Any {
322324
#[unstable(feature = "downcast_unchecked", issue = "90850")]
323325
#[inline]
324326
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
325-
debug_assert!(self.is::<T>());
327+
if core::ub_checks::check_library_ub() {
328+
assert!(self.is::<T>());
329+
}
326330
// SAFETY: caller guarantees that T is the correct type
327331
unsafe { &mut *(self as *mut dyn Any as *mut T) }
328332
}

0 commit comments

Comments
 (0)