Skip to content

Commit 51a8ce1

Browse files
authored
Rollup merge of rust-lang#73986 - RalfJung:raw-slice-as-ptr, r=sfackler
add (unchecked) indexing methods to raw (and NonNull) slices This complements the existing (unstable) `len` method. Unfortunately, for non-null slices, we cannot call this method `as_ptr` as that overlaps with the existing method of the same name. If this looks reasonable to accept, I propose to reuse the rust-lang#71146 tracking issue and rename the feature get to `slice_ptr_methods` or so. Cc @SimonSapin Fixes rust-lang#60639
2 parents 0663d5e + ff5e107 commit 51a8ce1

File tree

6 files changed

+287
-131
lines changed

6 files changed

+287
-131
lines changed

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@
148148
#![feature(associated_type_bounds)]
149149
#![feature(const_type_id)]
150150
#![feature(const_caller_location)]
151+
#![feature(slice_ptr_get)]
151152
#![feature(no_niche)] // rust-lang/rust#68303
152153
#![feature(unsafe_block_in_unsafe_fn)]
153154
#![deny(unsafe_op_in_unsafe_fn)]

src/libcore/ptr/const_ptr.rs

+50
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::*;
22
use crate::cmp::Ordering::{self, Equal, Greater, Less};
33
use crate::intrinsics;
44
use crate::mem;
5+
use crate::slice::SliceIndex;
56

67
#[lang = "const_ptr"]
78
impl<T: ?Sized> *const T {
@@ -826,6 +827,55 @@ impl<T> *const [T] {
826827
// Only `std` can make this guarantee.
827828
unsafe { Repr { rust: self }.raw }.len
828829
}
830+
831+
/// Returns a raw pointer to the slice's buffer.
832+
///
833+
/// This is equivalent to casting `self` to `*const T`, but more type-safe.
834+
///
835+
/// # Examples
836+
///
837+
/// ```rust
838+
/// #![feature(slice_ptr_get)]
839+
/// use std::ptr;
840+
///
841+
/// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3);
842+
/// assert_eq!(slice.as_ptr(), 0 as *const i8);
843+
/// ```
844+
#[inline]
845+
#[unstable(feature = "slice_ptr_get", issue = "74265")]
846+
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
847+
pub const fn as_ptr(self) -> *const T {
848+
self as *const T
849+
}
850+
851+
/// Returns a raw pointer to an element or subslice, without doing bounds
852+
/// checking.
853+
///
854+
/// Calling this method with an out-of-bounds index or when `self` is not dereferencable
855+
/// is *[undefined behavior]* even if the resulting pointer is not used.
856+
///
857+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
858+
///
859+
/// # Examples
860+
///
861+
/// ```
862+
/// #![feature(slice_ptr_get)]
863+
///
864+
/// let x = &[1, 2, 4] as *const [i32];
865+
///
866+
/// unsafe {
867+
/// assert_eq!(x.get_unchecked(1), x.as_ptr().add(1));
868+
/// }
869+
/// ```
870+
#[unstable(feature = "slice_ptr_get", issue = "74265")]
871+
#[inline]
872+
pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
873+
where
874+
I: SliceIndex<[T]>,
875+
{
876+
// SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
877+
unsafe { index.get_unchecked(self) }
878+
}
829879
}
830880

831881
// Equality for pointers

src/libcore/ptr/mut_ptr.rs

+50-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::*;
22
use crate::cmp::Ordering::{self, Equal, Greater, Less};
33
use crate::intrinsics;
4+
use crate::slice::SliceIndex;
45

56
#[lang = "mut_ptr"]
67
impl<T: ?Sized> *mut T {
@@ -1014,7 +1015,6 @@ impl<T> *mut [T] {
10141015
///
10151016
/// ```rust
10161017
/// #![feature(slice_ptr_len)]
1017-
///
10181018
/// use std::ptr;
10191019
///
10201020
/// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3);
@@ -1028,6 +1028,55 @@ impl<T> *mut [T] {
10281028
// Only `std` can make this guarantee.
10291029
unsafe { Repr { rust_mut: self }.raw }.len
10301030
}
1031+
1032+
/// Returns a raw pointer to the slice's buffer.
1033+
///
1034+
/// This is equivalent to casting `self` to `*mut T`, but more type-safe.
1035+
///
1036+
/// # Examples
1037+
///
1038+
/// ```rust
1039+
/// #![feature(slice_ptr_get)]
1040+
/// use std::ptr;
1041+
///
1042+
/// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3);
1043+
/// assert_eq!(slice.as_mut_ptr(), 0 as *mut i8);
1044+
/// ```
1045+
#[inline]
1046+
#[unstable(feature = "slice_ptr_get", issue = "74265")]
1047+
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
1048+
pub const fn as_mut_ptr(self) -> *mut T {
1049+
self as *mut T
1050+
}
1051+
1052+
/// Returns a raw pointer to an element or subslice, without doing bounds
1053+
/// checking.
1054+
///
1055+
/// Calling this method with an out-of-bounds index or when `self` is not dereferencable
1056+
/// is *[undefined behavior]* even if the resulting pointer is not used.
1057+
///
1058+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1059+
///
1060+
/// # Examples
1061+
///
1062+
/// ```
1063+
/// #![feature(slice_ptr_get)]
1064+
///
1065+
/// let x = &mut [1, 2, 4] as *mut [i32];
1066+
///
1067+
/// unsafe {
1068+
/// assert_eq!(x.get_unchecked_mut(1), x.as_mut_ptr().add(1));
1069+
/// }
1070+
/// ```
1071+
#[unstable(feature = "slice_ptr_get", issue = "74265")]
1072+
#[inline]
1073+
pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
1074+
where
1075+
I: SliceIndex<[T]>,
1076+
{
1077+
// SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
1078+
unsafe { index.get_unchecked_mut(self) }
1079+
}
10311080
}
10321081

10331082
// Equality for pointers

src/libcore/ptr/non_null.rs

+52-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::marker::Unsize;
66
use crate::mem;
77
use crate::ops::{CoerceUnsized, DispatchFromDyn};
88
use crate::ptr::Unique;
9+
use crate::slice::SliceIndex;
910

1011
/// `*mut T` but non-zero and covariant.
1112
///
@@ -192,7 +193,6 @@ impl<T> NonNull<[T]> {
192193
///
193194
/// ```rust
194195
/// #![feature(slice_ptr_len, nonnull_slice_from_raw_parts)]
195-
///
196196
/// use std::ptr::NonNull;
197197
///
198198
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
@@ -204,6 +204,57 @@ impl<T> NonNull<[T]> {
204204
pub const fn len(self) -> usize {
205205
self.as_ptr().len()
206206
}
207+
208+
/// Returns a non-null pointer to the slice's buffer.
209+
///
210+
/// # Examples
211+
///
212+
/// ```rust
213+
/// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)]
214+
/// use std::ptr::NonNull;
215+
///
216+
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
217+
/// assert_eq!(slice.as_non_null_ptr(), NonNull::new(1 as *mut i8).unwrap());
218+
/// ```
219+
#[inline]
220+
#[unstable(feature = "slice_ptr_get", issue = "74265")]
221+
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
222+
pub const fn as_non_null_ptr(self) -> NonNull<T> {
223+
// SAFETY: We know `self` is non-null.
224+
unsafe { NonNull::new_unchecked(self.as_ptr().as_mut_ptr()) }
225+
}
226+
227+
/// Returns a raw pointer to an element or subslice, without doing bounds
228+
/// checking.
229+
///
230+
/// Calling this method with an out-of-bounds index or when `self` is not dereferencable
231+
/// is *[undefined behavior]* even if the resulting pointer is not used.
232+
///
233+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
234+
///
235+
/// # Examples
236+
///
237+
/// ```
238+
/// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)]
239+
/// use std::ptr::NonNull;
240+
///
241+
/// let x = &mut [1, 2, 4];
242+
/// let x = NonNull::slice_from_raw_parts(NonNull::new(x.as_mut_ptr()).unwrap(), x.len());
243+
///
244+
/// unsafe {
245+
/// assert_eq!(x.get_unchecked_mut(1).as_ptr(), x.as_non_null_ptr().as_ptr().add(1));
246+
/// }
247+
/// ```
248+
#[unstable(feature = "slice_ptr_get", issue = "74265")]
249+
#[inline]
250+
pub unsafe fn get_unchecked_mut<I>(self, index: I) -> NonNull<I::Output>
251+
where
252+
I: SliceIndex<[T]>,
253+
{
254+
// SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
255+
// As a consequence, the resulting pointer cannot be NULL.
256+
unsafe { NonNull::new_unchecked(self.as_ptr().get_unchecked_mut(index)) }
257+
}
207258
}
208259

209260
#[stable(feature = "nonnull", since = "1.25.0")]

0 commit comments

Comments
 (0)