diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2019-05-21 15:37:07 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2019-05-21 15:37:07 -0700 |
| commit | fe3dd0b50fef21d14591c960a9610bafb224cdbf (patch) | |
| tree | ee0b62d8e500d4ce4b6f50b4fe5d9056b9826072 /src/libcore | |
| parent | e764f475ca7fffd6167ea991afc7d1b2b3f642dc (diff) | |
| parent | 50a0defd5a93523067ef239936cc2e0755220904 (diff) | |
| download | rust-fe3dd0b50fef21d14591c960a9610bafb224cdbf.tar.gz rust-fe3dd0b50fef21d14591c960a9610bafb224cdbf.zip | |
Merge remote-tracking branch 'origin/master' into azure-pipelines
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/alloc.rs | 6 | ||||
| -rw-r--r-- | src/libcore/array.rs | 9 | ||||
| -rw-r--r-- | src/libcore/ascii.rs | 2 | ||||
| -rw-r--r-- | src/libcore/convert.rs | 40 | ||||
| -rw-r--r-- | src/libcore/fmt/mod.rs | 4 | ||||
| -rw-r--r-- | src/libcore/future/future.rs | 2 | ||||
| -rw-r--r-- | src/libcore/iter/adapters/mod.rs | 5 | ||||
| -rw-r--r-- | src/libcore/iter/traits/iterator.rs | 32 | ||||
| -rw-r--r-- | src/libcore/lib.rs | 2 | ||||
| -rw-r--r-- | src/libcore/mem.rs | 412 | ||||
| -rw-r--r-- | src/libcore/ptr.rs | 23 | ||||
| -rw-r--r-- | src/libcore/slice/mod.rs | 26 | ||||
| -rw-r--r-- | src/libcore/str/mod.rs | 24 | ||||
| -rw-r--r-- | src/libcore/task/wake.rs | 23 | ||||
| -rw-r--r-- | src/libcore/tests/alloc.rs | 10 | ||||
| -rw-r--r-- | src/libcore/tests/lib.rs | 4 |
16 files changed, 340 insertions, 284 deletions
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index c124457118c..f25631e028e 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -99,7 +99,7 @@ impl Layout { /// [`Layout::from_size_align`](#method.from_size_align). #[stable(feature = "alloc_layout", since = "1.28.0")] #[inline] - pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { + pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) } } @@ -480,7 +480,7 @@ pub unsafe trait GlobalAlloc { /// this allocator, /// /// * `layout` must be the same layout that was used - /// to allocated that block of memory, + /// to allocate that block of memory, #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout); @@ -535,7 +535,7 @@ pub unsafe trait GlobalAlloc { /// * `ptr` must be currently allocated via this allocator, /// /// * `layout` must be the same layout that was used - /// to allocated that block of memory, + /// to allocate that block of memory, /// /// * `new_size` must be greater than zero. /// diff --git a/src/libcore/array.rs b/src/libcore/array.rs index e4cadcbf75b..03094bfd333 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -8,7 +8,7 @@ use crate::borrow::{Borrow, BorrowMut}; use crate::cmp::Ordering; -use crate::convert::TryFrom; +use crate::convert::{Infallible, TryFrom}; use crate::fmt; use crate::hash::{Hash, self}; use crate::marker::Unsize; @@ -74,6 +74,13 @@ impl TryFromSliceError { } } +#[stable(feature = "try_from_slice_error", since = "1.36.0")] +impl From<Infallible> for TryFromSliceError { + fn from(x: Infallible) -> TryFromSliceError { + match x {} + } +} + macro_rules! __impl_slice_eq1 { ($Lhs: ty, $Rhs: ty) => { __impl_slice_eq1! { $Lhs, $Rhs, Sized } diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index c0ab364380f..ddee02ea232 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -117,6 +117,8 @@ impl Iterator for EscapeDefault { type Item = u8; fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) } fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() } + #[inline] + fn last(mut self) -> Option<u8> { self.next_back() } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for EscapeDefault { diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index cf92babcb40..b3ff447be5e 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -104,7 +104,6 @@ pub const fn identity<T>(x: T) -> T { x } /// If you need to do a costly conversion it is better to implement [`From`] with type /// `&T` or write a custom function. /// -/// /// `AsRef` has the same signature as [`Borrow`], but `Borrow` is different in few aspects: /// /// - Unlike `AsRef`, `Borrow` has a blanket impl for any `T`, and can be used to accept either @@ -133,7 +132,7 @@ pub const fn identity<T>(x: T) -> T { x } /// converted a the specified type `T`. /// /// For example: By creating a generic function that takes an `AsRef<str>` we express that we -/// want to accept all references that can be converted to &str as an argument. +/// want to accept all references that can be converted to `&str` as an argument. /// Since both [`String`] and `&str` implement `AsRef<str>` we can accept both as input argument. /// /// [`String`]: ../../std/string/struct.String.html @@ -149,7 +148,6 @@ pub const fn identity<T>(x: T) -> T { x } /// let s = "hello".to_string(); /// is_hello(s); /// ``` -/// #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRef<T: ?Sized> { /// Performs the conversion. @@ -182,6 +180,7 @@ pub trait AsRef<T: ?Sized> { /// write a function `add_one`that takes all arguments that can be converted to `&mut u64`. /// Because [`Box<T>`] implements `AsMut<T>` `add_one` accepts arguments of type /// `&mut Box<u64>` as well: +/// /// ``` /// fn add_one<T: AsMut<u64>>(num: &mut T) { /// *num.as_mut() += 1; @@ -191,8 +190,8 @@ pub trait AsRef<T: ?Sized> { /// add_one(&mut boxed_num); /// assert_eq!(*boxed_num, 1); /// ``` -/// [`Box<T>`]: ../../std/boxed/struct.Box.html /// +/// [`Box<T>`]: ../../std/boxed/struct.Box.html #[stable(feature = "rust1", since = "1.0.0")] pub trait AsMut<T: ?Sized> { /// Performs the conversion. @@ -203,9 +202,9 @@ pub trait AsMut<T: ?Sized> { /// A value-to-value conversion that consumes the input value. The /// opposite of [`From`]. /// -/// One should only implement [`Into`] if a conversion to a type outside the current crate is -/// required. Otherwise one should always prefer implementing [`From`] over [`Into`] because -/// implementing [`From`] automatically provides one with a implementation of [`Into`] thanks to +/// One should only implement `Into` if a conversion to a type outside the current crate is +/// required. Otherwise one should always prefer implementing [`From`] over `Into` because +/// implementing [`From`] automatically provides one with a implementation of `Into` thanks to /// the blanket implementation in the standard library. [`From`] cannot do these type of /// conversions because of Rust's orphaning rules. /// @@ -213,8 +212,8 @@ pub trait AsMut<T: ?Sized> { /// /// # Generic Implementations /// -/// - [`From<T>`]` for U` implies `Into<U> for T` -/// - [`Into`]` is reflexive, which means that `Into<T> for T` is implemented +/// - [`From`]`<T> for U` implies `Into<U> for T` +/// - `Into` is reflexive, which means that `Into<T> for T` is implemented /// /// # Implementing `Into` for conversions to external types /// @@ -273,7 +272,7 @@ pub trait AsMut<T: ?Sized> { /// [`Option<T>`]: ../../std/option/enum.Option.html /// [`Result<T, E>`]: ../../std/result/enum.Result.html /// [`String`]: ../../std/string/struct.String.html -/// [From]: trait.From.html +/// [`From`]: trait.From.html /// [`into`]: trait.Into.html#tymethod.into #[stable(feature = "rust1", since = "1.0.0")] pub trait Into<T>: Sized { @@ -285,18 +284,18 @@ pub trait Into<T>: Sized { /// Used to do value-to-value conversions while consuming the input value. It is the reciprocal of /// [`Into`]. /// -/// One should always prefer implementing [`From`] over [`Into`] -/// because implementing [`From`] automatically provides one with a implementation of [`Into`] +/// One should always prefer implementing `From` over [`Into`] +/// because implementing `From` automatically provides one with a implementation of [`Into`] /// thanks to the blanket implementation in the standard library. /// /// Only implement [`Into`] if a conversion to a type outside the current crate is required. -/// [`From`] cannot do these type of conversions because of Rust's orphaning rules. +/// `From` cannot do these type of conversions because of Rust's orphaning rules. /// See [`Into`] for more details. /// -/// Prefer using [`Into`] over using [`From`] when specifying trait bounds on a generic function. +/// Prefer using [`Into`] over using `From` when specifying trait bounds on a generic function. /// This way, types that directly implement [`Into`] can be used as arguments as well. /// -/// The [`From`] is also very useful when performing error handling. When constructing a function +/// The `From` is also very useful when performing error handling. When constructing a function /// that is capable of failing, the return type will generally be of the form `Result<T, E>`. /// The `From` trait simplifies error handling by allowing a function to return a single error type /// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more @@ -306,14 +305,15 @@ pub trait Into<T>: Sized { /// /// # Generic Implementations /// -/// - [`From<T>`]` for U` implies [`Into<U>`]` for T` -/// - [`From`] is reflexive, which means that `From<T> for T` is implemented +/// - `From<T> for U` implies [`Into`]`<U> for T` +/// - `From` is reflexive, which means that `From<T> for T` is implemented /// /// # Examples /// /// [`String`] implements `From<&str>`: /// -/// An explicit conversion from a &str to a String is done as follows: +/// An explicit conversion from a `&str` to a String is done as follows: +/// /// ``` /// let string = "hello".to_string(); /// let other_string = String::from("hello"); @@ -361,7 +361,7 @@ pub trait Into<T>: Sized { /// [`Option<T>`]: ../../std/option/enum.Option.html /// [`Result<T, E>`]: ../../std/result/enum.Result.html /// [`String`]: ../../std/string/struct.String.html -/// [`Into<U>`]: trait.Into.html +/// [`Into`]: trait.Into.html /// [`from`]: trait.From.html#tymethod.from /// [book]: ../../book/ch09-00-error-handling.html #[stable(feature = "rust1", since = "1.0.0")] @@ -422,7 +422,7 @@ pub trait TryInto<T>: Sized { /// /// # Generic Implementations /// -/// - `TryFrom<T> for U` implies [`TryInto<U>`]` for T` +/// - `TryFrom<T> for U` implies [`TryInto`]`<U> for T` /// - [`try_from`] is reflexive, which means that `TryFrom<T> for T` /// is implemented and cannot fail -- the associated `Error` type for /// calling `T::try_from()` on a value of type `T` is `Infallible`. diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 43c1a3b7767..2f6d745d146 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -886,7 +886,7 @@ pub trait Pointer { /// /// # Examples /// -/// Basic usage with `i32`: +/// Basic usage with `f64`: /// /// ``` /// let x = 42.0; // 42.0 is '4.2e1' in scientific notation @@ -929,7 +929,7 @@ pub trait LowerExp { /// /// # Examples /// -/// Basic usage with `f32`: +/// Basic usage with `f64`: /// /// ``` /// let x = 42.0; // 42.0 is '4.2E1' in scientific notation diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 504330a023b..3f76ac20192 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -23,7 +23,7 @@ use crate::task::{Context, Poll}; /// When using a future, you generally won't call `poll` directly, but instead /// `await!` the value. #[doc(spotlight)] -#[must_use = "futures do nothing unless polled"] +#[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] pub trait Future { /// The type of value produced on completion. diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 518442efe74..64e588f65b4 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -73,6 +73,11 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator { { self.iter.position(predicate) } + + #[inline] + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 403f3358105..38c7c9bc4d0 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -356,7 +356,7 @@ pub trait Iterator { /// /// ``` /// let a = [0, 1, 2, 3, 4, 5]; - /// let mut iter = a.into_iter().step_by(2); + /// let mut iter = a.iter().step_by(2); /// /// assert_eq!(iter.next(), Some(&0)); /// assert_eq!(iter.next(), Some(&2)); @@ -531,7 +531,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.into_iter().map(|x| 2 * x); + /// let mut iter = a.iter().map(|x| 2 * x); /// /// assert_eq!(iter.next(), Some(2)); /// assert_eq!(iter.next(), Some(4)); @@ -620,7 +620,7 @@ pub trait Iterator { /// ``` /// let a = [0i32, 1, 2]; /// - /// let mut iter = a.into_iter().filter(|x| x.is_positive()); + /// let mut iter = a.iter().filter(|x| x.is_positive()); /// /// assert_eq!(iter.next(), Some(&1)); /// assert_eq!(iter.next(), Some(&2)); @@ -634,7 +634,7 @@ pub trait Iterator { /// ``` /// let a = [0, 1, 2]; /// - /// let mut iter = a.into_iter().filter(|x| **x > 1); // need two *s! + /// let mut iter = a.iter().filter(|x| **x > 1); // need two *s! /// /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), None); @@ -646,7 +646,7 @@ pub trait Iterator { /// ``` /// let a = [0, 1, 2]; /// - /// let mut iter = a.into_iter().filter(|&x| *x > 1); // both & and * + /// let mut iter = a.iter().filter(|&x| *x > 1); // both & and * /// /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), None); @@ -657,7 +657,7 @@ pub trait Iterator { /// ``` /// let a = [0, 1, 2]; /// - /// let mut iter = a.into_iter().filter(|&&x| x > 1); // two &s + /// let mut iter = a.iter().filter(|&&x| x > 1); // two &s /// /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), None); @@ -837,7 +837,7 @@ pub trait Iterator { /// ``` /// let a = [-1i32, 0, 1]; /// - /// let mut iter = a.into_iter().skip_while(|x| x.is_negative()); + /// let mut iter = a.iter().skip_while(|x| x.is_negative()); /// /// assert_eq!(iter.next(), Some(&0)); /// assert_eq!(iter.next(), Some(&1)); @@ -851,7 +851,7 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1]; /// - /// let mut iter = a.into_iter().skip_while(|x| **x < 0); // need two *s! + /// let mut iter = a.iter().skip_while(|x| **x < 0); // need two *s! /// /// assert_eq!(iter.next(), Some(&0)); /// assert_eq!(iter.next(), Some(&1)); @@ -863,7 +863,7 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1, -2]; /// - /// let mut iter = a.into_iter().skip_while(|x| **x < 0); + /// let mut iter = a.iter().skip_while(|x| **x < 0); /// /// assert_eq!(iter.next(), Some(&0)); /// assert_eq!(iter.next(), Some(&1)); @@ -898,7 +898,7 @@ pub trait Iterator { /// ``` /// let a = [-1i32, 0, 1]; /// - /// let mut iter = a.into_iter().take_while(|x| x.is_negative()); + /// let mut iter = a.iter().take_while(|x| x.is_negative()); /// /// assert_eq!(iter.next(), Some(&-1)); /// assert_eq!(iter.next(), None); @@ -911,7 +911,7 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1]; /// - /// let mut iter = a.into_iter().take_while(|x| **x < 0); // need two *s! + /// let mut iter = a.iter().take_while(|x| **x < 0); // need two *s! /// /// assert_eq!(iter.next(), Some(&-1)); /// assert_eq!(iter.next(), None); @@ -922,7 +922,7 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1, -2]; /// - /// let mut iter = a.into_iter().take_while(|x| **x < 0); + /// let mut iter = a.iter().take_while(|x| **x < 0); /// /// assert_eq!(iter.next(), Some(&-1)); /// @@ -937,7 +937,7 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3, 4]; - /// let mut iter = a.into_iter(); + /// let mut iter = a.iter(); /// /// let result: Vec<i32> = iter.by_ref() /// .take_while(|n| **n != 3) @@ -1321,7 +1321,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let iter = a.into_iter(); + /// let iter = a.iter(); /// /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i ); /// @@ -1334,7 +1334,7 @@ pub trait Iterator { /// // let's try that again /// let a = [1, 2, 3]; /// - /// let mut iter = a.into_iter(); + /// let mut iter = a.iter(); /// /// // instead, we add in a .by_ref() /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i ); @@ -1479,7 +1479,7 @@ pub trait Iterator { /// let a = [1, 2, 3]; /// /// let (even, odd): (Vec<i32>, Vec<i32>) = a - /// .into_iter() + /// .iter() /// .partition(|&n| n % 2 == 0); /// /// assert_eq!(even, vec![2]); diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 28db55578c3..4a70329b64b 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -125,7 +125,7 @@ #![feature(structural_match)] #![feature(abi_unadjusted)] #![feature(adx_target_feature)] -#![feature(maybe_uninit, maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_slice, maybe_uninit_array)] #![feature(external_doc)] #[prelude_import] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 9fb071d2952..24bee6355a7 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -63,62 +63,6 @@ pub use crate::intrinsics::transmute; /// The practical use cases for `forget` are rather specialized and mainly come /// up in unsafe or FFI code. /// -/// ## Use case 1 -/// -/// You have created an uninitialized value using [`mem::uninitialized`][uninit]. -/// You must either initialize or `forget` it on every computation path before -/// Rust drops it automatically, like at the end of a scope or after a panic. -/// Running the destructor on an uninitialized value would be [undefined behavior][ub]. -/// -/// ``` -/// use std::mem; -/// use std::ptr; -/// -/// # let some_condition = false; -/// unsafe { -/// let mut uninit_vec: Vec<u32> = mem::uninitialized(); -/// -/// if some_condition { -/// // Initialize the variable. -/// ptr::write(&mut uninit_vec, Vec::new()); -/// } else { -/// // Forget the uninitialized value so its destructor doesn't run. -/// mem::forget(uninit_vec); -/// } -/// } -/// ``` -/// -/// ## Use case 2 -/// -/// You have duplicated the bytes making up a value, without doing a proper -/// [`Clone`][clone]. You need the value's destructor to run only once, -/// because a double `free` is undefined behavior. -/// -/// An example is a possible implementation of [`mem::swap`][swap]: -/// -/// ``` -/// use std::mem; -/// use std::ptr; -/// -/// # #[allow(dead_code)] -/// fn swap<T>(x: &mut T, y: &mut T) { -/// unsafe { -/// // Give ourselves some scratch space to work with -/// let mut t: T = mem::uninitialized(); -/// -/// // Perform the swap, `&mut` pointers never alias -/// ptr::copy_nonoverlapping(&*x, &mut t, 1); -/// ptr::copy_nonoverlapping(&*y, x, 1); -/// ptr::copy_nonoverlapping(&t, y, 1); -/// -/// // y and t now point to the same thing, but we need to completely -/// // forget `t` because we do not want to run the destructor for `T` -/// // on its value, which is still owned somewhere outside this function. -/// mem::forget(t); -/// } -/// } -/// ``` -/// /// [drop]: fn.drop.html /// [uninit]: fn.uninitialized.html /// [clone]: ../clone/trait.Clone.html @@ -465,29 +409,37 @@ pub const fn needs_drop<T>() -> bool { /// Creates a value whose bytes are all zero. /// -/// This has the same effect as allocating space with -/// [`mem::uninitialized`][uninit] and then zeroing it out. It is useful for -/// FFI sometimes, but should generally be avoided. +/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed]. +/// It is useful for FFI sometimes, but should generally be avoided. /// /// There is no guarantee that an all-zero byte-pattern represents a valid value of -/// some type `T`. If `T` has a destructor and the value is destroyed (due to -/// a panic or the end of a scope) before being initialized, then the destructor -/// will run on zeroed data, likely leading to [undefined behavior][ub]. -/// -/// See also the documentation for [`mem::uninitialized`][uninit], which has -/// many of the same caveats. +/// some type `T`. For example, the all-zero byte-pattern is not a valid value +/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types +/// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv] +/// that there always is a valid value in a variable it considers initialized. /// -/// [uninit]: fn.uninitialized.html +/// [zeroed]: union.MaybeUninit.html#method.zeroed /// [ub]: ../../reference/behavior-considered-undefined.html +/// [inv]: union.MaybeUninit.html#initialization-invariant /// /// # Examples /// +/// Correct usage of this function: initializing an integer with zero. +/// /// ``` /// use std::mem; /// /// let x: i32 = unsafe { mem::zeroed() }; /// assert_eq!(0, x); /// ``` +/// +/// *Incorrect* usage of this function: initializing a reference with zero. +/// +/// ```no_run +/// use std::mem; +/// +/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! +/// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn zeroed<T>() -> T { @@ -498,130 +450,23 @@ pub unsafe fn zeroed<T>() -> T { /// Bypasses Rust's normal memory-initialization checks by pretending to /// produce a value of type `T`, while doing nothing at all. /// -/// **This is incredibly dangerous and should not be done lightly. Deeply -/// consider initializing your memory with a default value instead.** -/// -/// This is useful for FFI functions and initializing arrays sometimes, -/// but should generally be avoided. -/// -/// # Undefined behavior -/// -/// It is [undefined behavior][ub] to read uninitialized memory, even just an -/// uninitialized boolean. For instance, if you branch on the value of such -/// a boolean, your program may take one, both, or neither of the branches. -/// -/// Writing to the uninitialized value is similarly dangerous. Rust believes the -/// value is initialized, and will therefore try to [`Drop`] the uninitialized -/// value and its fields if you try to overwrite it in a normal manner. The only way -/// to safely initialize an uninitialized value is with [`ptr::write`][write], -/// [`ptr::copy`][copy], or [`ptr::copy_nonoverlapping`][copy_no]. -/// -/// If the value does implement [`Drop`], it must be initialized before -/// it goes out of scope (and therefore would be dropped). Note that this -/// includes a `panic` occurring and unwinding the stack suddenly. +/// **This functon is deprecated.** Use [`MaybeUninit<T>`] instead. /// -/// If you partially initialize an array, you may need to use -/// [`ptr::drop_in_place`][drop_in_place] to remove the elements you have fully -/// initialized followed by [`mem::forget`][mem_forget] to prevent drop running -/// on the array. If a partially allocated array is dropped this will lead to -/// undefined behaviour. -/// -/// # Examples -/// -/// Here's how to safely initialize an array of [`Vec`]s. -/// -/// ``` -/// use std::mem; -/// use std::ptr; -/// -/// // Only declare the array. This safely leaves it -/// // uninitialized in a way that Rust will track for us. -/// // However we can't initialize it element-by-element -/// // safely, and we can't use the `[value; 1000]` -/// // constructor because it only works with `Copy` data. -/// let mut data: [Vec<u32>; 1000]; -/// -/// unsafe { -/// // So we need to do this to initialize it. -/// data = mem::uninitialized(); -/// -/// // DANGER ZONE: if anything panics or otherwise -/// // incorrectly reads the array here, we will have -/// // Undefined Behavior. -/// -/// // It's ok to mutably iterate the data, since this -/// // doesn't involve reading it at all. -/// // (ptr and len are statically known for arrays) -/// for elem in &mut data[..] { -/// // *elem = Vec::new() would try to drop the -/// // uninitialized memory at `elem` -- bad! -/// // -/// // Vec::new doesn't allocate or do really -/// // anything. It's only safe to call here -/// // because we know it won't panic. -/// ptr::write(elem, Vec::new()); -/// } -/// -/// // SAFE ZONE: everything is initialized. -/// } -/// -/// println!("{:?}", &data[0]); -/// ``` -/// -/// This example emphasizes exactly how delicate and dangerous using `mem::uninitialized` -/// can be. Note that the [`vec!`] macro *does* let you initialize every element with a -/// value that is only [`Clone`], so the following is semantically equivalent and -/// vastly less dangerous, as long as you can live with an extra heap -/// allocation: -/// -/// ``` -/// let data: Vec<Vec<u32>> = vec![Vec::new(); 1000]; -/// println!("{:?}", &data[0]); -/// ``` -/// -/// This example shows how to handle partially initialized arrays, which could -/// be found in low-level datastructures. -/// -/// ``` -/// use std::mem; -/// use std::ptr; -/// -/// // Count the number of elements we have assigned. -/// let mut data_len: usize = 0; -/// let mut data: [String; 1000]; -/// -/// unsafe { -/// data = mem::uninitialized(); -/// -/// for elem in &mut data[0..500] { -/// ptr::write(elem, String::from("hello")); -/// data_len += 1; -/// } -/// -/// // For each item in the array, drop if we allocated it. -/// for i in &mut data[0..data_len] { -/// ptr::drop_in_place(i); -/// } -/// } -/// // Forget the data. If this is allowed to drop, you may see a crash such as: -/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object -/// // 0x7ff3b8402920: pointer being freed was not allocated' -/// mem::forget(data); -/// ``` +/// The reason for deprecation is that the function basically cannot be used +/// correctly: [the Rust compiler assumes][inv] that values are properly initialized. +/// As a consequence, calling e.g. `mem::uninitialized::<bool>()` causes immediate +/// undefined behavior for returning a `bool` that is not definitely either `true` +/// or `false`. Worse, truly uninitialized memory like what gets returned here +/// is special in that the compiler knows that it does not have a fixed value. +/// This makes it undefined behavior to have uninitialized data in a variable even +/// if that variable has an integer type. +/// (Notice that the rules around uninitialized integers are not finalized yet, but +/// until they are, it is advisable to avoid them.) /// -/// [`Vec`]: ../../std/vec/struct.Vec.html -/// [`vec!`]: ../../std/macro.vec.html -/// [`Clone`]: ../../std/clone/trait.Clone.html -/// [ub]: ../../reference/behavior-considered-undefined.html -/// [write]: ../ptr/fn.write.html -/// [drop_in_place]: ../ptr/fn.drop_in_place.html -/// [mem_zeroed]: fn.zeroed.html -/// [mem_forget]: fn.forget.html -/// [copy]: ../intrinsics/fn.copy.html -/// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html -/// [`Drop`]: ../ops/trait.Drop.html +/// [`MaybeUninit<T>`]: union.MaybeUninit.html +/// [inv]: union.MaybeUninit.html#initialization-invariant #[inline] -#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninit` instead")] +#[rustc_deprecated(since = "1.40.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn uninitialized<T>() -> T { intrinsics::panic_if_uninhabited::<T>(); @@ -899,7 +744,6 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> { } } -// FIXME: Reference `MaybeUninit` from these docs, once that is stable. /// A wrapper to inhibit compiler from automatically calling `T`’s destructor. /// /// This wrapper is 0-cost. @@ -908,6 +752,7 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> { /// As a consequence, it has *no effect* on the assumptions that the compiler makes /// about all values being initialized at their type. In particular, initializing /// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior. +/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead. /// /// # Examples /// @@ -942,6 +787,7 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> { /// ``` /// /// [`mem::zeroed`]: fn.zeroed.html +/// [`MaybeUninit<T>`]: union.MaybeUninit.html #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -1042,17 +888,18 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> { } } -/// A wrapper to construct uninitialized instances of `T`. +/// A wrapper type to construct uninitialized instances of `T`. +/// +/// # Initialization invariant /// /// The compiler, in general, assumes that variables are properly initialized /// at their respective type. For example, a variable of reference type must /// be aligned and non-NULL. This is an invariant that must *always* be upheld, /// even in unsafe code. As a consequence, zero-initializing a variable of reference -/// type causes instantaneous undefined behavior, no matter whether that reference +/// type causes instantaneous [undefined behavior][ub], no matter whether that reference /// ever gets used to access memory: /// /// ```rust,no_run -/// #![feature(maybe_uninit)] /// use std::mem::{self, MaybeUninit}; /// /// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! @@ -1067,7 +914,6 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> { /// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: /// /// ```rust,no_run -/// #![feature(maybe_uninit)] /// use std::mem::{self, MaybeUninit}; /// /// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! @@ -1078,10 +924,9 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> { /// Moreover, uninitialized memory is special in that the compiler knows that /// it does not have a fixed value. This makes it undefined behavior to have /// uninitialized data in a variable even if that variable has an integer type, -/// which otherwise can hold any bit pattern: +/// which otherwise can hold any *fixed* bit pattern: /// /// ```rust,no_run -/// #![feature(maybe_uninit)] /// use std::mem::{self, MaybeUninit}; /// /// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! @@ -1091,37 +936,154 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> { /// (Notice that the rules around uninitialized integers are not finalized yet, but /// until they are, it is advisable to avoid them.) /// +/// On top of that, remember that most types have additional invariants beyond merely +/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`] +/// is considered initialized because the only requirement the compiler knows about it +/// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause +/// *immediate* undefined behavior, but will cause undefined behavior with most +/// safe operations (including dropping it). +/// +/// [`Vec<T>`]: ../../std/vec/struct.Vec.html +/// +/// # Examples +/// /// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data. /// It is a signal to the compiler indicating that the data here might *not* /// be initialized: /// /// ```rust -/// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// // Create an explicitly uninitialized reference. The compiler knows that data inside /// // a `MaybeUninit<T>` may be invalid, and hence this is not UB: /// let mut x = MaybeUninit::<&i32>::uninit(); /// // Set it to a valid value. -/// x.write(&0); +/// unsafe { x.as_mut_ptr().write(&0); } /// // Extract the initialized data -- this is only allowed *after* properly /// // initializing `x`! /// let x = unsafe { x.assume_init() }; /// ``` /// /// The compiler then knows to not make any incorrect assumptions or optimizations on this code. -// -// FIXME before stabilizing, explain how to initialize a struct field-by-field. +/// +/// ## out-pointers +/// +/// You can use `MaybeUninit<T>` to implement "out-pointers": instead of returning data +/// from a function, pass it a pointer to some (uninitialized) memory to put the +/// result into. This can be useful when it is important for the caller to control +/// how the memory the result is stored in gets allocated, and you want to avoid +/// unnecessary moves. +/// +/// ``` +/// use std::mem::MaybeUninit; +/// +/// unsafe fn make_vec(out: *mut Vec<i32>) { +/// // `write` does not drop the old contents, which is important. +/// out.write(vec![1, 2, 3]); +/// } +/// +/// let mut v: MaybeUninit<Vec<i32>> = MaybeUninit::uninit(); +/// unsafe { make_vec(v.as_mut_ptr()); } +/// // Now we know `v` is initialized! This also makes sure the vector gets +/// // properly dropped. +/// let v = unsafe { v.assume_init() }; +/// assert_eq!(&v, &[1, 2, 3]); +/// ``` +/// +/// ## Initializing an array element-by-element +/// +/// `MaybeUninit<T>` can be used to initialize a large array element-by-element: +/// +/// ``` +/// use std::mem::{self, MaybeUninit}; +/// use std::ptr; +/// +/// let data = { +/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is +/// // safe because the type we are claiming to have initialized here is a +/// // bunch of `MaybeUninit`s, which do not require initialization. +/// let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe { +/// MaybeUninit::uninit().assume_init() +/// }; +/// +/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, +/// // we have a memory leak, but there is no memory safety issue. +/// for elem in &mut data[..] { +/// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); } +/// } +/// +/// // Everything is initialized. Transmute the array to the +/// // initialized type. +/// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) } +/// }; +/// +/// assert_eq!(&data[0], &[42]); +/// ``` +/// +/// You can also work with partially initialized arrays, which could +/// be found in low-level datastructures. +/// +/// ``` +/// use std::mem::MaybeUninit; +/// use std::ptr; +/// +/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is +/// // safe because the type we are claiming to have initialized here is a +/// // bunch of `MaybeUninit`s, which do not require initialization. +/// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() }; +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; +/// +/// for elem in &mut data[0..500] { +/// unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); } +/// data_len += 1; +/// } +/// +/// // For each item in the array, drop if we allocated it. +/// for elem in &mut data[0..data_len] { +/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); } +/// } +/// ``` +/// +/// ## Initializing a struct field-by-field +/// +/// There is currently no supported way to create a raw pointer or reference +/// to a field of a struct inside `MaybeUninit<Struct>`. That means it is not possible +/// to create a struct by calling `MaybeUninit::uninit::<Struct>()` and then writing +/// to its fields. +/// +/// [ub]: ../../reference/behavior-considered-undefined.html +/// +/// # Layout +/// +/// `MaybeUninit<T>` is guaranteed to have the same size and alignment as `T`: +/// +/// ```rust +/// use std::mem::{MaybeUninit, size_of, align_of}; +/// assert_eq!(size_of::<MaybeUninit<u64>>(), size_of::<u64>()); +/// assert_eq!(align_of::<MaybeUninit<u64>>(), align_of::<u64>()); +/// ``` +/// +/// However remember that a type *containing* a `MaybeUninit<T>` is not necessarily the same +/// layout; Rust does not in general guarantee that the fields of a `Foo<T>` have the same order as +/// a `Foo<U>` even if `T` and `U` have the same size and alignment. Furthermore because any bit +/// value is valid for a `MaybeUninit<T>` the compiler can't apply non-zero/niche-filling +/// optimizations, potentially resulting in a larger size: +/// +/// ```rust +/// # use std::mem::{MaybeUninit, size_of, align_of}; +/// assert_eq!(size_of::<Option<bool>>(), 1); +/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2); +/// ``` #[allow(missing_debug_implementations)] -#[unstable(feature = "maybe_uninit", issue = "53491")] +#[stable(feature = "maybe_uninit", since = "1.36.0")] #[derive(Copy)] -// NOTE: after stabilizing `MaybeUninit`, proceed to deprecate `mem::uninitialized`. pub union MaybeUninit<T> { uninit: (), value: ManuallyDrop<T>, } -#[unstable(feature = "maybe_uninit", issue = "53491")] +#[stable(feature = "maybe_uninit", since = "1.36.0")] impl<T: Copy> Clone for MaybeUninit<T> { #[inline(always)] fn clone(&self) -> Self { @@ -1132,10 +1094,13 @@ impl<T: Copy> Clone for MaybeUninit<T> { impl<T> MaybeUninit<T> { /// Creates a new `MaybeUninit<T>` initialized with the given value. + /// It is safe to call [`assume_init`] on the return value of this function. /// /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. - #[unstable(feature = "maybe_uninit", issue = "53491")] + /// + /// [`assume_init`]: #method.assume_init + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub const fn new(val: T) -> MaybeUninit<T> { MaybeUninit { value: ManuallyDrop::new(val) } @@ -1145,7 +1110,11 @@ impl<T> MaybeUninit<T> { /// /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. - #[unstable(feature = "maybe_uninit", issue = "53491")] + /// + /// See the [type-level documentation][type] for some examples. + /// + /// [type]: union.MaybeUninit.html + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub const fn uninit() -> MaybeUninit<T> { MaybeUninit { uninit: () } @@ -1166,7 +1135,6 @@ impl<T> MaybeUninit<T> { /// fields of the struct can hold the bit-pattern 0 as a valid value. /// /// ```rust - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let x = MaybeUninit::<(u8, bool)>::zeroed(); @@ -1178,7 +1146,6 @@ impl<T> MaybeUninit<T> { /// cannot hold 0 as a valid value. /// /// ```rust,no_run - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// enum NotZero { One = 1, Two = 2 }; @@ -1188,7 +1155,7 @@ impl<T> MaybeUninit<T> { /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. /// // This is undefined behavior. /// ``` - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline] pub fn zeroed() -> MaybeUninit<T> { let mut u = MaybeUninit::<T>::uninit(); @@ -1202,7 +1169,7 @@ impl<T> MaybeUninit<T> { /// without dropping it, so be careful not to use this twice unless you want to /// skip running the destructor. For your convenience, this also returns a mutable /// reference to the (now safely initialized) contents of `self`. - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "53491")] #[inline(always)] pub fn write(&mut self, val: T) -> &mut T { unsafe { @@ -1213,13 +1180,14 @@ impl<T> MaybeUninit<T> { /// Gets a pointer to the contained value. Reading from this pointer or turning it /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized. + /// Writing to memory that this pointer (non-transitively) points to is undefined behavior + /// (except inside an `UnsafeCell<T>`). /// /// # Examples /// /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); @@ -1232,7 +1200,6 @@ impl<T> MaybeUninit<T> { /// *Incorrect* usage of this method: /// /// ```rust,no_run - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let x = MaybeUninit::<Vec<u32>>::uninit(); @@ -1242,7 +1209,7 @@ impl<T> MaybeUninit<T> { /// /// (Notice that the rules around references to uninitialized data are not finalized yet, but /// until they are, it is advisable to avoid them.) - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub fn as_ptr(&self) -> *const T { unsafe { &*self.value as *const T } @@ -1256,7 +1223,6 @@ impl<T> MaybeUninit<T> { /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); @@ -1271,7 +1237,6 @@ impl<T> MaybeUninit<T> { /// *Incorrect* usage of this method: /// /// ```rust,no_run - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); @@ -1281,7 +1246,7 @@ impl<T> MaybeUninit<T> { /// /// (Notice that the rules around references to uninitialized data are not finalized yet, but /// until they are, it is advisable to avoid them.) - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub fn as_mut_ptr(&mut self) -> *mut T { unsafe { &mut *self.value as *mut T } @@ -1294,15 +1259,17 @@ impl<T> MaybeUninit<T> { /// # Safety /// /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. + /// state. Calling this when the content is not yet fully initialized causes immediate undefined + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. + /// + /// [inv]: #initialization-invariant /// /// # Examples /// /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::<bool>::uninit(); @@ -1314,14 +1281,13 @@ impl<T> MaybeUninit<T> { /// *Incorrect* usage of this method: /// /// ```rust,no_run - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let x = MaybeUninit::<Vec<u32>>::uninit(); /// let x_init = unsafe { x.assume_init() }; /// // `x` had not been initialized yet, so this last line caused undefined behavior. /// ``` - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub unsafe fn assume_init(self) -> T { intrinsics::panic_if_uninhabited::<T>(); @@ -1338,13 +1304,15 @@ impl<T> MaybeUninit<T> { /// /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. /// /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using /// multiple copies of the data (by calling `read` multiple times, or first /// calling `read` and then [`assume_init`]), it is your responsibility /// to ensure that that data may indeed be duplicated. /// + /// [inv]: #initialization-invariant /// [`assume_init`]: #method.assume_init /// /// # Examples @@ -1352,7 +1320,7 @@ impl<T> MaybeUninit<T> { /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit)] + /// #![feature(maybe_uninit_extra)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::<u32>::uninit(); @@ -1373,7 +1341,7 @@ impl<T> MaybeUninit<T> { /// *Incorrect* usage of this method: /// /// ```rust,no_run - /// #![feature(maybe_uninit)] + /// #![feature(maybe_uninit_extra)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit(); @@ -1383,7 +1351,7 @@ impl<T> MaybeUninit<T> { /// // We now created two copies of the same vector, leading to a double-free when /// // they both get dropped! /// ``` - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "53491")] #[inline(always)] pub unsafe fn read(&self) -> T { intrinsics::panic_if_uninhabited::<T>(); diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 6355bcdcab2..006b1e143ee 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -155,12 +155,12 @@ pub use crate::intrinsics::write_bytes; /// location first: /// ``` /// use std::ptr; -/// use std::mem; +/// use std::mem::{self, MaybeUninit}; /// /// unsafe fn drop_after_copy<T>(to_drop: *mut T) { -/// let mut copy: T = mem::uninitialized(); -/// ptr::copy(to_drop, &mut copy, 1); -/// drop(copy); +/// let mut copy: MaybeUninit<T> = MaybeUninit::uninit(); +/// ptr::copy(to_drop, copy.as_mut_ptr(), 1); +/// drop(copy.assume_init()); /// } /// /// #[repr(packed, C)] @@ -374,10 +374,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { // #[repr(simd)], even if we don't actually use this struct directly. // // FIXME repr(simd) broken on emscripten and redox - // It's also broken on big-endian powerpc64 and s390x. #42778 - #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox", - target_endian = "big")), - repr(simd))] + #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))] struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); @@ -813,9 +810,6 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { /// to not be elided or reordered by the compiler across other volatile /// operations. /// -/// Memory accessed with `read_volatile` or [`write_volatile`] should not be -/// accessed with non-volatile operations. -/// /// [`write_volatile`]: ./fn.write_volatile.html /// /// # Notes @@ -840,7 +834,7 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { /// /// * `src` must be properly aligned. /// -/// Like [`read`], `read_unaligned` creates a bitwise copy of `T`, regardless of +/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned /// value and the value at `*src` can [violate memory safety][read-ownership]. /// However, storing non-[`Copy`] types in volatile memory is almost certainly @@ -884,9 +878,6 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// -/// Memory accessed with [`read_volatile`] or `write_volatile` should not be -/// accessed with non-volatile operations. -/// /// `write_volatile` does not drop the contents of `dst`. This is safe, but it /// could leak allocations or resources, so care should be taken not to overwrite /// an object that should be dropped. @@ -2973,7 +2964,6 @@ impl<T: Sized> NonNull<T> { /// some other means. #[stable(feature = "nonnull", since = "1.25.0")] #[inline] - #[rustc_const_unstable(feature = "const_ptr_nonnull")] pub const fn dangling() -> Self { unsafe { let ptr = mem::align_of::<T>() as *mut T; @@ -3037,7 +3027,6 @@ impl<T: ?Sized> NonNull<T> { /// Cast to a pointer of another type #[stable(feature = "nonnull_cast", since = "1.27.0")] #[inline] - #[rustc_const_unstable(feature = "const_ptr_nonnull")] pub const fn cast<U>(self) -> NonNull<U> { unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f486753..d06d107d32a 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -359,6 +359,10 @@ impl<T> [T] { /// The caller must ensure that the slice outlives the pointer this /// function returns, or else it will end up pointing to garbage. /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// /// Modifying the container referenced by this slice may cause its buffer /// to be reallocated, which would also make any pointers to it invalid. /// @@ -374,6 +378,8 @@ impl<T> [T] { /// } /// } /// ``` + /// + /// [`as_mut_ptr`]: #method.as_mut_ptr #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub const fn as_ptr(&self) -> *const T { @@ -3541,6 +3547,11 @@ impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool { (1, Some(self.v.len() + 1)) } } + + #[inline] + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -3639,6 +3650,11 @@ impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool { (1, Some(self.v.len() + 1)) } } + + #[inline] + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -3704,6 +3720,11 @@ impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool { fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "slice_rsplit", since = "1.27.0")] @@ -3768,6 +3789,11 @@ impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool { fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "slice_rsplit", since = "1.27.0")] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 45421848cec..0e8a2da3c11 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1333,6 +1333,11 @@ impl<'a> Iterator for Lines<'a> { fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() } + + #[inline] + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1379,6 +1384,11 @@ impl<'a> Iterator for LinesAny<'a> { fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() } + + #[inline] + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2188,7 +2198,11 @@ impl str { /// [`u8`]. This pointer will be pointing to the first byte of the string /// slice. /// + /// The caller must ensure that the returned pointer is never written to. + /// If you need to mutate the contents of the string slice, use [`as_mut_ptr`]. + /// /// [`u8`]: primitive.u8.html + /// [`as_mut_ptr`]: #method.as_mut_ptr /// /// # Examples /// @@ -4217,6 +4231,11 @@ impl<'a> Iterator for SplitWhitespace<'a> { fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "split_whitespace", since = "1.1.0")] @@ -4243,6 +4262,11 @@ impl<'a> Iterator for SplitAsciiWhitespace<'a> { fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<Self::Item> { + self.next_back() + } } #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index b4e91249832..a6d611d2e93 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -10,6 +10,8 @@ use crate::marker::{PhantomData, Unpin}; /// /// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] that /// customizes the behavior of the `RawWaker`. +/// +/// [`Waker`]: struct.Waker.html #[derive(PartialEq, Debug)] #[stable(feature = "futures_api", since = "1.36.0")] pub struct RawWaker { @@ -55,6 +57,8 @@ impl RawWaker { /// pointer of a properly constructed [`RawWaker`] object from inside the /// [`RawWaker`] implementation. Calling one of the contained functions using /// any other `data` pointer will cause undefined behavior. +/// +/// [`RawWaker`]: struct.RawWaker.html #[stable(feature = "futures_api", since = "1.36.0")] #[derive(PartialEq, Copy, Clone, Debug)] pub struct RawWakerVTable { @@ -65,6 +69,9 @@ pub struct RawWakerVTable { /// required for this additional instance of a [`RawWaker`] and associated /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup /// of the same task that would have been awoken by the original [`RawWaker`]. + /// + /// [`Waker`]: struct.Waker.html + /// [`RawWaker`]: struct.RawWaker.html clone: unsafe fn(*const ()) -> RawWaker, /// This function will be called when `wake` is called on the [`Waker`]. @@ -73,6 +80,9 @@ pub struct RawWakerVTable { /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and /// associated task. + /// + /// [`Waker`]: struct.Waker.html + /// [`RawWaker`]: struct.RawWaker.html wake: unsafe fn(*const ()), /// This function will be called when `wake_by_ref` is called on the [`Waker`]. @@ -80,6 +90,9 @@ pub struct RawWakerVTable { /// /// This function is similar to `wake`, but must not consume the provided data /// pointer. + /// + /// [`Waker`]: struct.Waker.html + /// [`RawWaker`]: struct.RawWaker.html wake_by_ref: unsafe fn(*const ()), /// This function gets called when a [`RawWaker`] gets dropped. @@ -87,6 +100,8 @@ pub struct RawWakerVTable { /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and /// associated task. + /// + /// [`RawWaker`]: struct.RawWaker.html drop: unsafe fn(*const ()), } @@ -128,6 +143,9 @@ impl RawWakerVTable { /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and /// associated task. + /// + /// [`Waker`]: struct.Waker.html + /// [`RawWaker`]: struct.RawWaker.html #[rustc_promotable] #[cfg_attr(stage0, unstable(feature = "futures_api_const_fn_ptr", issue = "50547"))] #[cfg_attr(not(stage0), stable(feature = "futures_api", since = "1.36.0"))] @@ -201,6 +219,8 @@ impl fmt::Debug for Context<'_> { /// executor-specific wakeup behavior. /// /// Implements [`Clone`], [`Send`], and [`Sync`]. +/// +/// [`RawWaker`]: struct.RawWaker.html #[repr(transparent)] #[stable(feature = "futures_api", since = "1.36.0")] pub struct Waker { @@ -266,6 +286,9 @@ impl Waker { /// The behavior of the returned `Waker` is undefined if the contract defined /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. /// Therefore this method is unsafe. + /// + /// [`RawWaker`]: struct.RawWaker.html + /// [`RawWakerVTable`]: struct.RawWakerVTable.html #[inline] #[stable(feature = "futures_api", since = "1.36.0")] pub unsafe fn from_raw(waker: RawWaker) -> Waker { diff --git a/src/libcore/tests/alloc.rs b/src/libcore/tests/alloc.rs new file mode 100644 index 00000000000..63537ba23d8 --- /dev/null +++ b/src/libcore/tests/alloc.rs @@ -0,0 +1,10 @@ +use core::alloc::Layout; + +#[test] +fn const_unchecked_layout() { + const SIZE: usize = 0x2000; + const ALIGN: usize = 0x1000; + const LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(SIZE, ALIGN) }; + assert_eq!(LAYOUT.size(), SIZE); + assert_eq!(LAYOUT.align(), ALIGN); +} diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 025f7fb5cc6..c617596aba8 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -31,10 +31,12 @@ #![feature(slice_partition_dedup)] #![feature(copy_within)] #![feature(int_error_matching)] -#![deny(rust_2018_idioms)] +#![feature(const_fn)] +#![warn(rust_2018_idioms)] extern crate test; +mod alloc; mod any; mod array; mod ascii; |
