diff options
| author | bors <bors@rust-lang.org> | 2022-05-12 02:49:00 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-05-12 02:49:00 +0000 |
| commit | 1d2ea98cff1fde1d8b9e83a0eb639b8ec2cb82d8 (patch) | |
| tree | 5a6932062880a7b698c794abb827ac1f39192948 /src/test/ui/consts | |
| parent | 0cd939e36c0696aad44a213566c9b152f0437020 (diff) | |
| parent | 003b954a43a7f1f9058f25e8f9b6ddfd4a3dced9 (diff) | |
| download | rust-1d2ea98cff1fde1d8b9e83a0eb639b8ec2cb82d8.tar.gz rust-1d2ea98cff1fde1d8b9e83a0eb639b8ec2cb82d8.zip | |
Auto merge of #95837 - scottmcm:ptr-offset-from-unsigned, r=oli-obk
Add `sub_ptr` on pointers (the `usize` version of `offset_from`) We have `add`/`sub` which are the `usize` versions of `offset`, this adds the `usize` equivalent of `offset_from`. Like how `.add(d)` replaced a whole bunch of `.offset(d as isize)`, you can see from the changes here that it's fairly common that code actually knows the order between the pointers and *wants* a `usize`, not an `isize`. As a bonus, this can do `sub nuw`+`udiv exact`, rather than `sub`+`sdiv exact`, which can be optimized slightly better because it doesn't have to worry about negatives. That's why the slice iterators weren't using `offset_from`, though I haven't updated that code in this PR because slices are so perf-critical that I'll do it as its own change. This is an intrinsic, like `offset_from`, so that it can eventually be allowed in CTFE. It also allows checking the extra safety condition -- see the test confirming that CTFE catches it if you pass the pointers in the wrong order.
Diffstat (limited to 'src/test/ui/consts')
| -rw-r--r-- | src/test/ui/consts/offset_from.rs | 9 | ||||
| -rw-r--r-- | src/test/ui/consts/offset_from_ub.rs | 21 | ||||
| -rw-r--r-- | src/test/ui/consts/offset_from_ub.stderr | 14 |
3 files changed, 41 insertions, 3 deletions
diff --git a/src/test/ui/consts/offset_from.rs b/src/test/ui/consts/offset_from.rs index 4c9b1c1571d..b53718316f3 100644 --- a/src/test/ui/consts/offset_from.rs +++ b/src/test/ui/consts/offset_from.rs @@ -1,6 +1,8 @@ // run-pass #![feature(const_ptr_offset_from)] +#![feature(const_ptr_sub_ptr)] +#![feature(ptr_sub_ptr)] struct Struct { field: (), @@ -43,9 +45,16 @@ pub const OFFSET_EQUAL_INTS: isize = { unsafe { ptr.offset_from(ptr) } }; +pub const OFFSET_UNSIGNED: usize = { + let a = ['a', 'b', 'c']; + let ptr = a.as_ptr(); + unsafe { ptr.add(2).sub_ptr(ptr) } +}; + fn main() { assert_eq!(OFFSET, 0); assert_eq!(OFFSET_2, 1); assert_eq!(OVERFLOW, -1); assert_eq!(OFFSET_EQUAL_INTS, 0); + assert_eq!(OFFSET_UNSIGNED, 2); } diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs index 939c1e31f9a..f604f57e39d 100644 --- a/src/test/ui/consts/offset_from_ub.rs +++ b/src/test/ui/consts/offset_from_ub.rs @@ -1,7 +1,7 @@ #![feature(const_ptr_offset_from)] #![feature(core_intrinsics)] -use std::intrinsics::ptr_offset_from; +use std::intrinsics::{ptr_offset_from, ptr_offset_from_unsigned}; #[repr(C)] struct Struct { @@ -15,7 +15,7 @@ pub const DIFFERENT_ALLOC: usize = { let uninit2 = std::mem::MaybeUninit::<Struct>::uninit(); let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct; let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed - //~| cannot compute offset of pointers into different allocations. + //~| ptr_offset_from cannot compute offset of pointers into different allocations. offset as usize }; @@ -70,4 +70,21 @@ const OUT_OF_BOUNDS_SAME: isize = { //~| pointer at offset 10 is out-of-bounds }; +pub const DIFFERENT_ALLOC_UNSIGNED: usize = { + let uninit = std::mem::MaybeUninit::<Struct>::uninit(); + let base_ptr: *const Struct = &uninit as *const _ as *const Struct; + let uninit2 = std::mem::MaybeUninit::<Struct>::uninit(); + let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct; + let offset = unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed + //~| ptr_offset_from_unsigned cannot compute offset of pointers into different allocations. + offset as usize +}; + +const WRONG_ORDER_UNSIGNED: usize = { + let a = ['a', 'b', 'c']; + let p = a.as_ptr(); + unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } //~ERROR evaluation of constant value failed + //~| cannot compute a negative offset, but 0 < 8 +}; + fn main() {} diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index 293a2b47d30..4c98fd72cac 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -54,6 +54,18 @@ error[E0080]: evaluation of constant value failed LL | unsafe { ptr_offset_from(end_ptr, end_ptr) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc26 has size 4, so pointer at offset 10 is out-of-bounds -error: aborting due to 8 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:78:27 + | +LL | let offset = unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from_unsigned cannot compute offset of pointers into different allocations. + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:86:14 + | +LL | unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from_unsigned cannot compute a negative offset, but 0 < 8 + +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0080`. |
