about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLzu Tao <taolzu@gmail.com>2020-09-04 04:46:02 +0000
committerLzu Tao <taolzu@gmail.com>2020-09-14 09:35:54 +0000
commitbcd18f977bee4db79d42d54cc7edce19c942b963 (patch)
tree85be95ece4bcee8f2aa3356d710f131277c0f5d6
parentf376443b8f2e8935c33f1edd08586ec7f29a900c (diff)
downloadrust-bcd18f977bee4db79d42d54cc7edce19c942b963.tar.gz
rust-bcd18f977bee4db79d42d54cc7edce19c942b963.zip
Move free functions to a new module
-rw-r--r--library/core/src/slice/mod.rs184
-rw-r--r--library/core/src/slice/raw.rs158
-rw-r--r--library/core/src/slice/sort.rs3
3 files changed, 172 insertions, 173 deletions
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index bbaf0fae05a..87ce4e0e12b 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -17,15 +17,12 @@
 //
 // * Inherent methods. This is where most of the slice API resides.
 // * Implementations of a few common traits with important slice ops.
-// * Definitions of a bunch of iterators.
-// * Free functions.
 // * The `raw` and `bytes` submodules.
 // * Boilerplate trait implementations.
 
 use crate::cmp;
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
-use crate::intrinsics::{assume, is_aligned_and_not_null};
-use crate::iter::*;
+use crate::intrinsics::assume;
 use crate::marker::{self, Copy, Sized};
 use crate::mem;
 use crate::ops::{self, Bound, FnMut, Range, RangeBounds};
@@ -44,6 +41,7 @@ use crate::result::Result::{Err, Ok};
 pub mod memchr;
 
 mod iter;
+mod raw;
 mod rotate;
 mod sort;
 
@@ -71,6 +69,16 @@ pub use iter::{ArrayChunks, ArrayChunksMut};
 #[unstable(feature = "split_inclusive", issue = "72360")]
 pub use iter::{SplitInclusive, SplitInclusiveMut};
 
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use raw::{from_raw_parts, from_raw_parts_mut};
+
+#[stable(feature = "from_ref", since = "1.28.0")]
+pub use raw::{from_mut, from_ref};
+
+// This function is public only because there is no other way to unit test heapsort.
+#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "none")]
+pub use sort::heapsort;
+
 //
 // Extension traits
 //
@@ -3806,174 +3814,6 @@ impl<T> Default for &mut [T] {
     }
 }
 
-//
-// Free functions
-//
-
-/// Forms a slice from a pointer and a length.
-///
-/// The `len` argument is the number of **elements**, not the number of bytes.
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `data` must be [valid] for reads for `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!
-///       Slices can never span across multiple allocated objects. See [below](#incorrect-usage)
-///       for an example incorrectly not taking this into account.
-///     * `data` must be non-null and aligned even for zero-length slices. One
-///       reason for this is that enum layout optimizations may rely on references
-///       (including slices of any length) being aligned and non-null to distinguish
-///       them from other data. You can obtain a pointer that is usable as `data`
-///       for zero-length slices using [`NonNull::dangling()`].
-///
-/// * `data` must point to `len` consecutive properly initialized values of type `T`.
-///
-/// * The memory referenced by the returned slice must not be mutated for the duration
-///   of lifetime `'a`, except inside an `UnsafeCell`.
-///
-/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
-///   See the safety documentation of [`pointer::offset`].
-///
-/// # Caveat
-///
-/// The lifetime for the returned slice is inferred from its usage. To
-/// prevent accidental misuse, it's suggested to tie the lifetime to whichever
-/// source lifetime is safe in the context, such as by providing a helper
-/// function taking the lifetime of a host value for the slice, or by explicit
-/// annotation.
-///
-/// # Examples
-///
-/// ```
-/// use std::slice;
-///
-/// // manifest a slice for a single element
-/// let x = 42;
-/// let ptr = &x as *const _;
-/// let slice = unsafe { slice::from_raw_parts(ptr, 1) };
-/// assert_eq!(slice[0], 42);
-/// ```
-///
-/// ### Incorrect usage
-///
-/// The following `join_slices` function is **unsound** ⚠️
-///
-/// ```rust,no_run
-/// use std::slice;
-///
-/// fn join_slices<'a, T>(fst: &'a [T], snd: &'a [T]) -> &'a [T] {
-///     let fst_end = fst.as_ptr().wrapping_add(fst.len());
-///     let snd_start = snd.as_ptr();
-///     assert_eq!(fst_end, snd_start, "Slices must be contiguous!");
-///     unsafe {
-///         // The assertion above ensures `fst` and `snd` are contiguous, but they might
-///         // still be contained within _different allocated objects_, in which case
-///         // creating this slice is undefined behavior.
-///         slice::from_raw_parts(fst.as_ptr(), fst.len() + snd.len())
-///     }
-/// }
-///
-/// fn main() {
-///     // `a` and `b` are different allocated objects...
-///     let a = 42;
-///     let b = 27;
-///     // ... which may nevertheless be laid out contiguously in memory: | a | b |
-///     let _ = join_slices(slice::from_ref(&a), slice::from_ref(&b)); // UB
-/// }
-/// ```
-///
-/// [valid]: ptr#safety
-/// [`NonNull::dangling()`]: ptr::NonNull::dangling
-/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
-    debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
-    debug_assert!(
-        mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
-        "attempt to create slice covering at least half the address space"
-    );
-    // SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
-    unsafe { &*ptr::slice_from_raw_parts(data, len) }
-}
-
-/// Performs the same functionality as [`from_raw_parts`], except that a
-/// mutable slice is returned.
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `data` must be [valid] for boths reads and writes for `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!
-///       Slices can never span across multiple allocated objects.
-///     * `data` must be non-null and aligned even for zero-length slices. One
-///       reason for this is that enum layout optimizations may rely on references
-///       (including slices of any length) being aligned and non-null to distinguish
-///       them from other data. You can obtain a pointer that is usable as `data`
-///       for zero-length slices using [`NonNull::dangling()`].
-///
-/// * `data` must point to `len` consecutive properly initialized values of type `T`.
-///
-/// * The memory referenced by the returned slice must not be accessed through any other pointer
-///   (not derived from the return value) for the duration of lifetime `'a`.
-///   Both read and write accesses are forbidden.
-///
-/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
-///   See the safety documentation of [`pointer::offset`].
-///
-/// [valid]: ptr#safety
-/// [`NonNull::dangling()`]: ptr::NonNull::dangling
-/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
-    debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
-    debug_assert!(
-        mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
-        "attempt to create slice covering at least half the address space"
-    );
-    // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
-    unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
-}
-
-/// Converts a reference to T into a slice of length 1 (without copying).
-#[stable(feature = "from_ref", since = "1.28.0")]
-pub fn from_ref<T>(s: &T) -> &[T] {
-    // SAFETY: a reference is guaranteed to be valid for reads. The returned
-    // reference cannot be mutated as it is an immutable reference.
-    // `mem::size_of::<T>()` cannot be larger than `isize::MAX`.
-    // Thus the call to `from_raw_parts` is safe.
-    unsafe { from_raw_parts(s, 1) }
-}
-
-/// Converts a reference to T into a slice of length 1 (without copying).
-#[stable(feature = "from_ref", since = "1.28.0")]
-pub fn from_mut<T>(s: &mut T) -> &mut [T] {
-    // SAFETY: a mutable reference is guaranteed to be valid for writes.
-    // The reference cannot be accessed by another pointer as it is an mutable reference.
-    // `mem::size_of::<T>()` cannot be larger than `isize::MAX`.
-    // Thus the call to `from_raw_parts_mut` is safe.
-    unsafe { from_raw_parts_mut(s, 1) }
-}
-
-// This function is public only because there is no other way to unit test heapsort.
-#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "none")]
-#[doc(hidden)]
-pub fn heapsort<T, F>(v: &mut [T], mut is_less: F)
-where
-    F: FnMut(&T, &T) -> bool,
-{
-    sort::heapsort(v, &mut is_less);
-}
-
-//
 // Comparison traits
 //
 
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
new file mode 100644
index 00000000000..a5811c5e472
--- /dev/null
+++ b/library/core/src/slice/raw.rs
@@ -0,0 +1,158 @@
+//! Free functions to create `&[T]` and `&mut [T]`.
+
+use crate::intrinsics::is_aligned_and_not_null;
+use crate::mem;
+use crate::ptr;
+
+/// Forms a slice from a pointer and a length.
+///
+/// The `len` argument is the number of **elements**, not the number of bytes.
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `data` must be [valid] for reads for `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!
+///       Slices can never span across multiple allocated objects. See [below](#incorrect-usage)
+///       for an example incorrectly not taking this into account.
+///     * `data` must be non-null and aligned even for zero-length slices. One
+///       reason for this is that enum layout optimizations may rely on references
+///       (including slices of any length) being aligned and non-null to distinguish
+///       them from other data. You can obtain a pointer that is usable as `data`
+///       for zero-length slices using [`NonNull::dangling()`].
+///
+/// * `data` must point to `len` consecutive properly initialized values of type `T`.
+///
+/// * The memory referenced by the returned slice must not be mutated for the duration
+///   of lifetime `'a`, except inside an `UnsafeCell`.
+///
+/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+///   See the safety documentation of [`pointer::offset`].
+///
+/// # Caveat
+///
+/// The lifetime for the returned slice is inferred from its usage. To
+/// prevent accidental misuse, it's suggested to tie the lifetime to whichever
+/// source lifetime is safe in the context, such as by providing a helper
+/// function taking the lifetime of a host value for the slice, or by explicit
+/// annotation.
+///
+/// # Examples
+///
+/// ```
+/// use std::slice;
+///
+/// // manifest a slice for a single element
+/// let x = 42;
+/// let ptr = &x as *const _;
+/// let slice = unsafe { slice::from_raw_parts(ptr, 1) };
+/// assert_eq!(slice[0], 42);
+/// ```
+///
+/// ### Incorrect usage
+///
+/// The following `join_slices` function is **unsound** ⚠️
+///
+/// ```rust,no_run
+/// use std::slice;
+///
+/// fn join_slices<'a, T>(fst: &'a [T], snd: &'a [T]) -> &'a [T] {
+///     let fst_end = fst.as_ptr().wrapping_add(fst.len());
+///     let snd_start = snd.as_ptr();
+///     assert_eq!(fst_end, snd_start, "Slices must be contiguous!");
+///     unsafe {
+///         // The assertion above ensures `fst` and `snd` are contiguous, but they might
+///         // still be contained within _different allocated objects_, in which case
+///         // creating this slice is undefined behavior.
+///         slice::from_raw_parts(fst.as_ptr(), fst.len() + snd.len())
+///     }
+/// }
+///
+/// fn main() {
+///     // `a` and `b` are different allocated objects...
+///     let a = 42;
+///     let b = 27;
+///     // ... which may nevertheless be laid out contiguously in memory: | a | b |
+///     let _ = join_slices(slice::from_ref(&a), slice::from_ref(&b)); // UB
+/// }
+/// ```
+///
+/// [valid]: ptr#safety
+/// [`NonNull::dangling()`]: ptr::NonNull::dangling
+/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
+    debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
+    debug_assert!(
+        mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
+        "attempt to create slice covering at least half the address space"
+    );
+    // SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
+    unsafe { &*ptr::slice_from_raw_parts(data, len) }
+}
+
+/// Performs the same functionality as [`from_raw_parts`], except that a
+/// mutable slice is returned.
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `data` must be [valid] for boths reads and writes for `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!
+///       Slices can never span across multiple allocated objects.
+///     * `data` must be non-null and aligned even for zero-length slices. One
+///       reason for this is that enum layout optimizations may rely on references
+///       (including slices of any length) being aligned and non-null to distinguish
+///       them from other data. You can obtain a pointer that is usable as `data`
+///       for zero-length slices using [`NonNull::dangling()`].
+///
+/// * `data` must point to `len` consecutive properly initialized values of type `T`.
+///
+/// * The memory referenced by the returned slice must not be accessed through any other pointer
+///   (not derived from the return value) for the duration of lifetime `'a`.
+///   Both read and write accesses are forbidden.
+///
+/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
+///   See the safety documentation of [`pointer::offset`].
+///
+/// [valid]: ptr#safety
+/// [`NonNull::dangling()`]: ptr::NonNull::dangling
+/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
+    debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
+    debug_assert!(
+        mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
+        "attempt to create slice covering at least half the address space"
+    );
+    // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
+    unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
+}
+
+/// Converts a reference to T into a slice of length 1 (without copying).
+#[stable(feature = "from_ref", since = "1.28.0")]
+pub fn from_ref<T>(s: &T) -> &[T] {
+    // SAFETY: a reference is guaranteed to be valid for reads. The returned
+    // reference cannot be mutated as it is an immutable reference.
+    // `mem::size_of::<T>()` cannot be larger than `isize::MAX`.
+    // Thus the call to `from_raw_parts` is safe.
+    unsafe { from_raw_parts(s, 1) }
+}
+
+/// Converts a reference to T into a slice of length 1 (without copying).
+#[stable(feature = "from_ref", since = "1.28.0")]
+pub fn from_mut<T>(s: &mut T) -> &mut [T] {
+    // SAFETY: a mutable reference is guaranteed to be valid for writes.
+    // The reference cannot be accessed by another pointer as it is an mutable reference.
+    // `mem::size_of::<T>()` cannot be larger than `isize::MAX`.
+    // Thus the call to `from_raw_parts_mut` is safe.
+    unsafe { from_raw_parts_mut(s, 1) }
+}
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index 4a00124fcff..8c14651bd82 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -180,7 +180,8 @@ where
 
 /// Sorts `v` using heapsort, which guarantees *O*(*n* \* log(*n*)) worst-case.
 #[cold]
-pub fn heapsort<T, F>(v: &mut [T], is_less: &mut F)
+#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "none")]
+pub fn heapsort<T, F>(v: &mut [T], mut is_less: F)
 where
     F: FnMut(&T, &T) -> bool,
 {