mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-31 05:26:23 +03:00
Auto merge of #83674 - Dylan-DPC:rollup-bcuc1hl, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #83568 (update comment at MaybeUninit::uninit_array) - #83571 (Constantify some slice methods) - #83579 (Improve pointer arithmetic docs) - #83645 (Wrap non-pre code blocks) - #83656 (Add a regression test for issue-82865) - #83662 (Update books) - #83667 (Suggest box/pin/arc ing receiver on method calls) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
@@ -319,9 +319,9 @@ pub const fn uninit() -> MaybeUninit<T> {
|
||||
/// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
|
||||
///
|
||||
/// Note: in a future Rust version this method may become unnecessary
|
||||
/// when array literal syntax allows
|
||||
/// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147).
|
||||
/// The example below could then use `let mut buf = [MaybeUninit::<u8>::uninit(); 32];`.
|
||||
/// when Rust allows
|
||||
/// [inline const expressions](https://github.com/rust-lang/rust/issues/76001).
|
||||
/// The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
||||
@@ -184,8 +184,7 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
|
||||
///
|
||||
@@ -210,6 +209,7 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_offset`]: #method.wrapping_offset
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -245,9 +245,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@@ -265,10 +264,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
|
||||
/// words, leaving the allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`offset`]: #method.offset
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -314,8 +311,7 @@ pub const fn wrapping_offset(self, count: isize) -> *const T
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and other pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * Both pointers must be *derived from* a pointer to the same object.
|
||||
/// (See below for an example.)
|
||||
@@ -345,6 +341,7 @@ pub const fn wrapping_offset(self, count: isize) -> *const T
|
||||
/// such large allocations either.)
|
||||
///
|
||||
/// [`add`]: #method.add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@@ -468,8 +465,7 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
|
||||
///
|
||||
@@ -494,6 +490,7 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_add`]: #method.wrapping_add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -532,8 +529,7 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
|
||||
///
|
||||
@@ -558,6 +554,7 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_sub`]: #method.wrapping_sub
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -594,9 +591,8 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@@ -614,10 +610,8 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
|
||||
/// allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`add`]: #method.add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -659,9 +653,8 @@ pub const fn wrapping_add(self, count: usize) -> Self
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@@ -679,10 +672,8 @@ pub const fn wrapping_add(self, count: usize) -> Self
|
||||
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
|
||||
/// allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`sub`]: #method.sub
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -997,7 +988,7 @@ pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
|
||||
/// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
|
||||
/// and it must be properly aligned. This means in particular:
|
||||
///
|
||||
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||
/// * The entire memory range of this slice must be contained within a single [allocated object]!
|
||||
/// Slices can never span across multiple allocated objects.
|
||||
///
|
||||
/// * The pointer must be aligned even for zero-length slices. One
|
||||
@@ -1019,6 +1010,7 @@ pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
|
||||
/// See also [`slice::from_raw_parts`][].
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
|
||||
|
||||
@@ -55,6 +55,14 @@
|
||||
//! has size 0, i.e., even if memory is not actually touched. Consider using
|
||||
//! [`NonNull::dangling`] in such cases.
|
||||
//!
|
||||
//! ## Allocated object
|
||||
//!
|
||||
//! For several operations, such as [`offset`] or field projections (`expr.field`), the notion of an
|
||||
//! "allocated object" becomes relevant. An allocated object is a contiguous region of memory.
|
||||
//! Common examples of allocated objects include stack-allocated variables (each variable is a
|
||||
//! separate allocated object), heap allocations (each allocation created by the global allocator is
|
||||
//! a separate allocated object), and `static` variables.
|
||||
//!
|
||||
//! [aliasing]: ../../nomicon/aliasing.html
|
||||
//! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer
|
||||
//! [ub]: ../../reference/behavior-considered-undefined.html
|
||||
|
||||
@@ -189,8 +189,7 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
|
||||
///
|
||||
@@ -215,6 +214,7 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_offset`]: #method.wrapping_offset
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -251,9 +251,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@@ -271,10 +270,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
|
||||
/// words, leaving the allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`offset`]: #method.offset
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -485,8 +482,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and other pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * Both pointers must be *derived from* a pointer to the same object.
|
||||
/// (See below for an example.)
|
||||
@@ -516,6 +512,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// such large allocations either.)
|
||||
///
|
||||
/// [`add`]: #method.add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@@ -575,8 +572,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
|
||||
///
|
||||
@@ -639,8 +635,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
|
||||
///
|
||||
@@ -665,6 +660,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_sub`]: #method.wrapping_sub
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -701,9 +697,8 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@@ -721,10 +716,8 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
|
||||
/// allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`add`]: #method.add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -766,9 +759,8 @@ pub const fn wrapping_add(self, count: usize) -> Self
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@@ -786,10 +778,8 @@ pub const fn wrapping_add(self, count: usize) -> Self
|
||||
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
|
||||
/// allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`sub`]: #method.sub
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -1261,7 +1251,7 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
|
||||
/// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
|
||||
/// and it must be properly aligned. This means in particular:
|
||||
///
|
||||
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||
/// * The entire memory range of this slice must be contained within a single [allocated object]!
|
||||
/// Slices can never span across multiple allocated objects.
|
||||
///
|
||||
/// * The pointer must be aligned even for zero-length slices. One
|
||||
@@ -1283,6 +1273,7 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
|
||||
/// See also [`slice::from_raw_parts`][].
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
|
||||
@@ -1311,7 +1302,7 @@ pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
|
||||
/// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::<T>()`
|
||||
/// many bytes, and it must be properly aligned. This means in particular:
|
||||
///
|
||||
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||
/// * The entire memory range of this slice must be contained within a single [allocated object]!
|
||||
/// Slices can never span across multiple allocated objects.
|
||||
///
|
||||
/// * The pointer must be aligned even for zero-length slices. One
|
||||
@@ -1333,6 +1324,7 @@ pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
|
||||
/// See also [`slice::from_raw_parts_mut`][].
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
|
||||
|
||||
@@ -148,8 +148,9 @@ pub const fn is_empty(&self) -> bool {
|
||||
/// assert_eq!(None, w.first());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn first(&self) -> Option<&T> {
|
||||
pub const fn first(&self) -> Option<&T> {
|
||||
if let [first, ..] = self { Some(first) } else { None }
|
||||
}
|
||||
|
||||
@@ -166,8 +167,9 @@ pub fn first(&self) -> Option<&T> {
|
||||
/// assert_eq!(x, &[5, 1, 2]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn first_mut(&mut self) -> Option<&mut T> {
|
||||
pub const fn first_mut(&mut self) -> Option<&mut T> {
|
||||
if let [first, ..] = self { Some(first) } else { None }
|
||||
}
|
||||
|
||||
@@ -184,8 +186,9 @@ pub fn first_mut(&mut self) -> Option<&mut T> {
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "slice_splits", since = "1.5.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn split_first(&self) -> Option<(&T, &[T])> {
|
||||
pub const fn split_first(&self) -> Option<(&T, &[T])> {
|
||||
if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
|
||||
}
|
||||
|
||||
@@ -204,8 +207,9 @@ pub fn split_first(&self) -> Option<(&T, &[T])> {
|
||||
/// assert_eq!(x, &[3, 4, 5]);
|
||||
/// ```
|
||||
#[stable(feature = "slice_splits", since = "1.5.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
|
||||
}
|
||||
|
||||
@@ -222,8 +226,9 @@ pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "slice_splits", since = "1.5.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn split_last(&self) -> Option<(&T, &[T])> {
|
||||
pub const fn split_last(&self) -> Option<(&T, &[T])> {
|
||||
if let [init @ .., last] = self { Some((last, init)) } else { None }
|
||||
}
|
||||
|
||||
@@ -242,8 +247,9 @@ pub fn split_last(&self) -> Option<(&T, &[T])> {
|
||||
/// assert_eq!(x, &[4, 5, 3]);
|
||||
/// ```
|
||||
#[stable(feature = "slice_splits", since = "1.5.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
if let [init @ .., last] = self { Some((last, init)) } else { None }
|
||||
}
|
||||
|
||||
@@ -259,8 +265,9 @@ pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
/// assert_eq!(None, w.last());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn last(&self) -> Option<&T> {
|
||||
pub const fn last(&self) -> Option<&T> {
|
||||
if let [.., last] = self { Some(last) } else { None }
|
||||
}
|
||||
|
||||
@@ -277,8 +284,9 @@ pub fn last(&self) -> Option<&T> {
|
||||
/// assert_eq!(x, &[0, 1, 10]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn last_mut(&mut self) -> Option<&mut T> {
|
||||
pub const fn last_mut(&mut self) -> Option<&mut T> {
|
||||
if let [.., last] = self { Some(last) } else { None }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user