Skip to content

Commit 5f5c98b

Browse files
committed
add (unchecked) indexing methods to raw pointers and NonNull
1 parent 90580c7 commit 5f5c98b

File tree

4 files changed

+103
-15
lines changed

4 files changed

+103
-15
lines changed

src/libcore/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@
9393
#![feature(const_slice_ptr_len)]
9494
#![feature(const_type_name)]
9595
#![feature(const_likely)]
96-
#![feature(const_slice_ptr_ptr)]
9796
#![feature(custom_inner_attributes)]
9897
#![feature(decl_macro)]
9998
#![feature(doc_cfg)]
@@ -149,6 +148,7 @@
149148
#![feature(associated_type_bounds)]
150149
#![feature(const_type_id)]
151150
#![feature(const_caller_location)]
151+
#![feature(slice_ptr_get)]
152152
#![feature(no_niche)] // rust-lang/rust#68303
153153
#![feature(unsafe_block_in_unsafe_fn)]
154154
#![deny(unsafe_op_in_unsafe_fn)]

src/libcore/ptr/const_ptr.rs

+33-4
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 {
@@ -834,19 +835,47 @@ impl<T> *const [T] {
834835
/// # Examples
835836
///
836837
/// ```rust
837-
/// #![feature(slice_ptr_ptr)]
838-
///
838+
/// #![feature(slice_ptr_get)]
839839
/// use std::ptr;
840840
///
841841
/// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3);
842842
/// assert_eq!(slice.as_ptr(), 0 as *const i8);
843843
/// ```
844844
#[inline]
845-
#[unstable(feature = "slice_ptr_ptr", issue = "none")]
846-
#[rustc_const_unstable(feature = "const_slice_ptr_ptr", issue = "none")]
845+
#[unstable(feature = "slice_ptr_get", issue = "none")]
846+
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "none")]
847847
pub const fn as_ptr(self) -> *const T {
848848
self as *const T
849849
}
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 = "none")]
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+
}
850879
}
851880

852881
// Equality for pointers

src/libcore/ptr/mut_ptr.rs

+33-5
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);
@@ -1036,19 +1036,47 @@ impl<T> *mut [T] {
10361036
/// # Examples
10371037
///
10381038
/// ```rust
1039-
/// #![feature(slice_ptr_ptr)]
1040-
///
1039+
/// #![feature(slice_ptr_get)]
10411040
/// use std::ptr;
10421041
///
10431042
/// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3);
10441043
/// assert_eq!(slice.as_mut_ptr(), 0 as *mut i8);
10451044
/// ```
10461045
#[inline]
1047-
#[unstable(feature = "slice_ptr_ptr", issue = "none")]
1048-
#[rustc_const_unstable(feature = "const_slice_ptr_ptr", issue = "none")]
1046+
#[unstable(feature = "slice_ptr_get", issue = "none")]
1047+
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "none")]
10491048
pub const fn as_mut_ptr(self) -> *mut T {
10501049
self as *mut T
10511050
}
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 = "none")]
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+
}
10521080
}
10531081

10541082
// Equality for pointers

src/libcore/ptr/non_null.rs

+36-5
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);
@@ -210,20 +210,51 @@ impl<T> NonNull<[T]> {
210210
/// # Examples
211211
///
212212
/// ```rust
213-
/// #![feature(slice_ptr_ptr, nonnull_slice_from_raw_parts)]
214-
///
213+
/// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)]
215214
/// use std::ptr::NonNull;
216215
///
217216
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
218217
/// assert_eq!(slice.as_non_null_ptr(), NonNull::new(1 as *mut i8).unwrap());
219218
/// ```
220219
#[inline]
221-
#[unstable(feature = "slice_ptr_ptr", issue = "none")]
222-
#[rustc_const_unstable(feature = "const_slice_ptr_ptr", issue = "none")]
220+
#[unstable(feature = "slice_ptr_get", issue = "none")]
221+
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "none")]
223222
pub const fn as_non_null_ptr(self) -> NonNull<T> {
224223
// SAFETY: We know `self` is non-null.
225224
unsafe { NonNull::new_unchecked(self.as_ptr().as_mut_ptr()) }
226225
}
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 = "none")]
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+
}
227258
}
228259

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

0 commit comments

Comments
 (0)