|
1 | 1 | use super::*;
|
2 | 2 | use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
3 | 3 | use crate::intrinsics::{self, const_eval_select};
|
4 |
| -use crate::mem; |
| 4 | +use crate::mem::{self, SizedTypeProperties}; |
5 | 5 | use crate::slice::{self, SliceIndex};
|
6 | 6 |
|
7 | 7 | impl<T: ?Sized> *const T {
|
@@ -995,14 +995,23 @@ impl<T: ?Sized> *const T {
|
995 | 995 | #[stable(feature = "pointer_methods", since = "1.26.0")]
|
996 | 996 | #[must_use = "returns a new pointer rather than modifying its argument"]
|
997 | 997 | #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
| 998 | + // We could always go back to wrapping if unchecked becomes unacceptable |
| 999 | + #[rustc_allow_const_fn_unstable(const_int_unchecked_arith)] |
998 | 1000 | #[inline(always)]
|
999 | 1001 | #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
1000 | 1002 | pub const unsafe fn sub(self, count: usize) -> Self
|
1001 | 1003 | where
|
1002 | 1004 | T: Sized,
|
1003 | 1005 | {
|
1004 |
| - // SAFETY: the caller must uphold the safety contract for `offset`. |
1005 |
| - unsafe { self.offset((count as isize).wrapping_neg()) } |
| 1006 | + if T::IS_ZST { |
| 1007 | + // Pointer arithmetic does nothing when the pointee is a ZST. |
| 1008 | + self |
| 1009 | + } else { |
| 1010 | + // SAFETY: the caller must uphold the safety contract for `offset`. |
| 1011 | + // Because the pointee is *not* a ZST, that means that `count` is |
| 1012 | + // at most `isize::MAX`, and thus the negation cannot overflow. |
| 1013 | + unsafe { self.offset(intrinsics::unchecked_sub(0, count as isize)) } |
| 1014 | + } |
1006 | 1015 | }
|
1007 | 1016 |
|
1008 | 1017 | /// Calculates the offset from a pointer in bytes (convenience for
|
|
0 commit comments