diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 7756a6f71dbd6..56a24168e28d9 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -962,59 +962,127 @@ extern "rust-intrinsic" { /// value is not necessarily valid to be used to actually access memory. pub fn arith_offset(dst: *const T, offset: isize) -> *const T; - /// Copies `count * size_of` bytes from `src` to `dst`. The source - /// and destination may *not* overlap. + /// Copies `count * size_of::()` bytes from `src` to `dst`. The source + /// and destination must *not* overlap. /// - /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`. + /// For regions of memory which might overlap, use [`copy`] instead. + /// + /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but + /// with the argument order swapped. + /// + /// [`copy`]: ./fn.copy.html + /// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy /// /// # Safety /// - /// Beyond requiring that the program must be allowed to access both regions - /// of memory, it is Undefined Behavior for source and destination to - /// overlap. Care must also be taken with the ownership of `src` and - /// `dst`. This method semantically moves the values of `src` into `dst`. - /// However it does not drop the contents of `dst`, or prevent the contents - /// of `src` from being dropped or used. + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * `src` must be [valid] for reads of `count * size_of::()` bytes. + /// + /// * `dst` must be [valid] for writes of `count * size_of::()` bytes. + /// + /// * Both `src` and `dst` must be properly aligned. + /// + /// * The region of memory beginning at `src` with a size of `count * + /// size_of::()` bytes must *not* overlap with the region of memory + /// beginning at `dst` with the same size. + /// + /// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of + /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values + /// in the region beginning at `*src` and the region beginning at `*dst` can + /// [violate memory safety][read-ownership]. + /// + /// Note that even if the effectively copied size (`count * size_of::()`) is + /// `0`, the pointers must be non-NULL and properly aligned. + /// + /// [`Copy`]: ../marker/trait.Copy.html + /// [`read`]: ../ptr/fn.read.html + /// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value + /// [valid]: ../ptr/index.html#safety /// /// # Examples /// - /// A safe swap function: + /// Manually implement [`Vec::append`]: /// /// ``` - /// use std::mem; /// use std::ptr; /// - /// # #[allow(dead_code)] - /// fn swap(x: &mut T, y: &mut T) { - /// unsafe { - /// // Give ourselves some scratch space to work with - /// let mut t: T = mem::uninitialized(); + /// /// Moves all the elements of `src` into `dst`, leaving `src` empty. + /// fn append(dst: &mut Vec, src: &mut Vec) { + /// let src_len = src.len(); + /// let dst_len = dst.len(); /// - /// // 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); + /// // Ensure that `dst` has enough capacity to hold all of `src`. + /// dst.reserve(src_len); /// - /// // y and t now point to the same thing, but we need to completely forget `t` - /// // because it's no longer relevant. - /// mem::forget(t); + /// unsafe { + /// // The call to offset is always safe because `Vec` will never + /// // allocate more than `isize::MAX` bytes. + /// let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize); + /// let src_ptr = src.as_ptr(); + /// + /// // Truncate `src` without dropping its contents. We do this first, + /// // to avoid problems in case something further down panics. + /// src.set_len(0); + /// + /// // The two regions cannot overlap becuase mutable references do + /// // not alias, and two different vectors cannot own the same + /// // memory. + /// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len); + /// + /// // Notify `dst` that it now holds the contents of `src`. + /// dst.set_len(dst_len + src_len); /// } /// } + /// + /// let mut a = vec!['r']; + /// let mut b = vec!['u', 's', 't']; + /// + /// append(&mut a, &mut b); + /// + /// assert_eq!(a, &['r', 'u', 's', 't']); + /// assert!(b.is_empty()); /// ``` + /// + /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append #[stable(feature = "rust1", since = "1.0.0")] pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); - /// Copies `count * size_of` bytes from `src` to `dst`. The source + /// Copies `count * size_of::()` bytes from `src` to `dst`. The source /// and destination may overlap. /// - /// `copy` is semantically equivalent to C's `memmove`. + /// If the source and destination will *never* overlap, + /// [`copy_nonoverlapping`] can be used instead. + /// + /// `copy` is semantically equivalent to C's [`memmove`], but with the argument + /// order swapped. Copying takes place as if the bytes were copied from `src` + /// to a temporary array and then copied from the array to `dst`. + /// + /// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html + /// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove /// /// # Safety /// - /// Care must be taken with the ownership of `src` and `dst`. - /// This method semantically moves the values of `src` into `dst`. - /// However it does not drop the contents of `dst`, or prevent the contents of `src` - /// from being dropped or used. + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * `src` must be [valid] for reads of `count * size_of::()` bytes. + /// + /// * `dst` must be [valid] for writes of `count * size_of::()` bytes. + /// + /// * Both `src` and `dst` must be properly aligned. + /// + /// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of + /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values + /// in the region beginning at `*src` and the region beginning at `*dst` can + /// [violate memory safety][read-ownership]. + /// + /// Note that even if the effectively copied size (`count * size_of::()`) is + /// `0`, the pointers must be non-NULL and properly aligned. + /// + /// [`Copy`]: ../marker/trait.Copy.html + /// [`read`]: ../ptr/fn.read.html + /// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value + /// [valid]: ../ptr/index.html#safety /// /// # Examples /// @@ -1031,24 +1099,80 @@ extern "rust-intrinsic" { /// dst /// } /// ``` - /// #[stable(feature = "rust1", since = "1.0.0")] pub fn copy(src: *const T, dst: *mut T, count: usize); - /// Invokes memset on the specified pointer, setting `count * size_of::()` - /// bytes of memory starting at `dst` to `val`. + /// Sets `count * size_of::()` bytes of memory starting at `dst` to + /// `val`. + /// + /// `write_bytes` is similar to C's [`memset`], but sets `count * + /// size_of::()` bytes to `val`. + /// + /// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset + /// + /// # Safety + /// + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * `dst` must be [valid] for writes of `count * size_of::()` bytes. + /// + /// * `dst` must be properly aligned. + /// + /// Additionally, the caller must ensure that writing `count * + /// size_of::()` bytes to the given region of memory results in a valid + /// value of `T`. Using a region of memory typed as a `T` that contains an + /// invalid value of `T` is undefined behavior. + /// + /// Note that even if the effectively copied size (`count * size_of::()`) is + /// `0`, the pointer must be non-NULL and properly aligned. + /// + /// [valid]: ../ptr/index.html#safety /// /// # Examples /// + /// Basic usage: + /// /// ``` /// use std::ptr; /// - /// let mut vec = vec![0; 4]; + /// let mut vec = vec![0u32; 4]; /// unsafe { /// let vec_ptr = vec.as_mut_ptr(); - /// ptr::write_bytes(vec_ptr, b'a', 2); + /// ptr::write_bytes(vec_ptr, 0xfe, 2); + /// } + /// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]); + /// ``` + /// + /// Creating an invalid value: + /// + /// ``` + /// use std::ptr; + /// + /// let mut v = Box::new(0i32); + /// + /// unsafe { + /// // Leaks the previously held value by overwriting the `Box` with + /// // a null pointer. + /// ptr::write_bytes(&mut v as *mut Box, 0, 1); /// } - /// assert_eq!(vec, [b'a', b'a', 0, 0]); + /// + /// // At this point, using or dropping `v` results in undefined behavior. + /// // drop(v); // ERROR + /// + /// // Even leaking `v` "uses" it, and hence is undefined behavior. + /// // mem::forget(v); // ERROR + /// + /// // In fact, `v` is invalid according to basic type layout invariants, so *any* + /// // operation touching it is undefined behavior. + /// // let v2 = v; // ERROR + /// + /// unsafe { + /// // Let us instead put in a valid value + /// ptr::write(&mut v as *mut Box, Box::new(42i32)); + /// } + /// + /// // Now the box is fine + /// assert_eq!(*v, 42); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn write_bytes(dst: *mut T, val: u8, count: usize); @@ -1066,7 +1190,7 @@ extern "rust-intrinsic" { /// `min_align_of::()` /// /// The volatile parameter is set to `true`, so it will not be optimized out - /// unless size is equal to zero.. + /// unless size is equal to zero. pub fn volatile_copy_memory(dst: *mut T, src: *const T, count: usize); /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a /// size of `count` * `size_of::()` and an alignment of diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 57351822cc3cf..14f2148a64e0e 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -8,11 +8,68 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME: talk about offset, copy_memory, copy_nonoverlapping_memory - -//! Raw, unsafe pointers, `*const T`, and `*mut T`. +//! Manually manage memory through raw pointers. //! //! *[See also the pointer primitive types](../../std/primitive.pointer.html).* +//! +//! # Safety +//! +//! Many functions in this module take raw pointers as arguments and read from +//! or write to them. For this to be safe, these pointers must be *valid*. +//! Whether a pointer is valid depends on the operation it is used for +//! (read or write), and the extent of the memory that is accessed (i.e., +//! how many bytes are read/written). Most functions use `*mut T` and `*const T` +//! to access only a single value, in which case the documentation omits the size +//! and implicitly assumes it to be `size_of::()` bytes. +//! +//! The precise rules for validity are not determined yet. The guarantees that are +//! provided at this point are very minimal: +//! +//! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst]. +//! * All pointers (except for the null pointer) are valid for all operations of +//! [size zero][zst]. +//! * All accesses performed by functions in this module are *non-atomic* in the sense +//! of [atomic operations] used to synchronize between threads. This means it is +//! undefined behavior to perform two concurrent accesses to the same location from different +//! threads unless both accesses only read from memory. Notice that this explicitly +//! includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot +//! be used for inter-thread synchronization. +//! * The result of casting a reference to a pointer is valid for as long as the +//! underlying object is live and no reference (just raw pointers) is used to +//! access the same memory. +//! +//! These axioms, along with careful use of [`offset`] for pointer arithmentic, +//! are enough to correctly implement many useful things in unsafe code. Stronger guarantees +//! will be provided eventually, as the [aliasing] rules are being determined. For more +//! information, see the [book] as well as the section in the reference devoted +//! to [undefined behavior][ub]. +//! +//! ## Alignment +//! +//! Valid raw pointers as defined above are not necessarily properly aligned (where +//! "proper" alignment is defined by the pointee type, i.e., `*const T` must be +//! aligned to `mem::align_of::()`). However, most functions require their +//! arguments to be properly aligned, and will explicitly state +//! this requirement in their documentation. Notable exceptions to this are +//! [`read_unaligned`] and [`write_unaligned`]. +//! +//! When a function requires proper alignment, it does so even if the access +//! has size 0, i.e., even if memory is not actually touched. Consider using +//! [`NonNull::dangling`] in such cases. +//! +//! [aliasing]: ../../nomicon/aliasing.html +//! [book]: ../../book/second-edition/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer +//! [ub]: ../../reference/behavior-considered-undefined.html +//! [null]: ./fn.null.html +//! [zst]: ../../nomicon/exotic-sizes.html#zero-sized-types-zsts +//! [atomic operations]: ../../std/sync/atomic/index.html +//! [`copy`]: ../../std/ptr/fn.copy.html +//! [`offset`]: ../../std/primitive.pointer.html#method.offset +//! [`read_unaligned`]: ./fn.read_unaligned.html +//! [`write_unaligned`]: ./fn.write_unaligned.html +//! [`read_volatile`]: ./fn.read_volatile.html +//! [`write_volatile`]: ./fn.write_volatile.html +//! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling #![stable(feature = "rust1", since = "1.0.0")] @@ -38,21 +95,99 @@ pub use intrinsics::write_bytes; /// Executes the destructor (if any) of the pointed-to value. /// -/// This has two use cases: +/// This is semantically equivalent to calling [`ptr::read`] and discarding +/// the result, but has the following advantages: /// /// * It is *required* to use `drop_in_place` to drop unsized types like /// trait objects, because they can't be read out onto the stack and /// dropped normally. /// -/// * It is friendlier to the optimizer to do this over `ptr::read` when +/// * It is friendlier to the optimizer to do this over [`ptr::read`] when /// dropping manually allocated memory (e.g. when writing Box/Rc/Vec), /// as the compiler doesn't need to prove that it's sound to elide the /// copy. /// +/// [`ptr::read`]: ../ptr/fn.read.html +/// /// # Safety /// -/// This has all the same safety problems as `ptr::read` with respect to -/// invalid pointers, types, and double drops. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `to_drop` must be [valid] for reads. +/// +/// * `to_drop` must be properly aligned. See the example below for how to drop +/// an unaligned pointer. +/// +/// Additionally, if `T` is not [`Copy`], using the pointed-to value after +/// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop = +/// foo` counts as a use because it will cause the the value to be dropped +/// again. [`write`] can be used to overwrite data without causing it to be +/// dropped. +/// +/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// +/// [valid]: ../ptr/index.html#safety +/// [`Copy`]: ../marker/trait.Copy.html +/// [`write`]: ../ptr/fn.write.html +/// +/// # Examples +/// +/// Manually remove the last item from a vector: +/// +/// ``` +/// use std::ptr; +/// use std::rc::Rc; +/// +/// let last = Rc::new(1); +/// let weak = Rc::downgrade(&last); +/// +/// let mut v = vec![Rc::new(0), last]; +/// +/// unsafe { +/// // Get a raw pointer to the last element in `v`. +/// let ptr = &mut v[1] as *mut _; +/// // Shorten `v` to prevent the last item from being dropped. We do that first, +/// // to prevent issues if the `drop_in_place` below panics. +/// v.set_len(1); +/// // Without a call `drop_in_place`, the last item would never be dropped, +/// // and the memory it manages would be leaked. +/// ptr::drop_in_place(ptr); +/// } +/// +/// assert_eq!(v, &[0.into()]); +/// +/// // Ensure that the last item was dropped. +/// assert!(weak.upgrade().is_none()); +/// ``` +/// +/// Unaligned values cannot be dropped in place, they must be copied to an aligned +/// location first: +/// ``` +/// use std::ptr; +/// use std::mem; +/// +/// unsafe fn drop_after_copy(to_drop: *mut T) { +/// let mut copy: T = mem::uninitialized(); +/// ptr::copy(to_drop, &mut copy, 1); +/// drop(copy); +/// } +/// +/// #[repr(packed, C)] +/// struct Packed { +/// _padding: u8, +/// unaligned: Vec, +/// } +/// +/// let mut p = Packed { _padding: 0, unaligned: vec![42] }; +/// unsafe { +/// drop_after_copy(&mut p.unaligned as *mut _); +/// mem::forget(p); +/// } +/// ``` +/// +/// Notice that the compiler performs this copy automatically when dropping packed structs, +/// i.e., you do not usually have to worry about such issues unless you call `drop_in_place` +/// manually. #[stable(feature = "drop_in_place", since = "1.8.0")] #[lang = "drop_in_place"] #[allow(unconditional_recursion)] @@ -93,17 +228,29 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } /// Swaps the values at two mutable locations of the same type, without /// deinitializing either. /// -/// The values pointed at by `x` and `y` may overlap, unlike `mem::swap` which -/// is otherwise equivalent. If the values do overlap, then the overlapping -/// region of memory from `x` will be used. This is demonstrated in the -/// examples section below. +/// But for the following two exceptions, this function is semantically +/// equivalent to [`mem::swap`]: +/// +/// * It operates on raw pointers instead of references. When references are +/// available, [`mem::swap`] should be preferred. +/// +/// * The two pointed-to values may overlap. If the values do overlap, then the +/// overlapping region of memory from `x` will be used. This is demonstrated +/// in the second example below. +/// +/// [`mem::swap`]: ../mem/fn.swap.html /// /// # Safety /// -/// This function copies the memory through the raw pointers passed to it -/// as arguments. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * Both `x` and `y` must be [valid] for reads and writes. +/// +/// * Both `x` and `y` must be properly aligned. /// -/// Ensure that these pointers are valid before calling `swap`. +/// Note that even if `T` has size `0`, the pointers must be non-NULL and properly aligned. +/// +/// [valid]: ../ptr/index.html#safety /// /// # Examples /// @@ -114,8 +261,8 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } /// /// let mut array = [0, 1, 2, 3]; /// -/// let x = array[0..].as_mut_ptr() as *mut [u32; 2]; -/// let y = array[2..].as_mut_ptr() as *mut [u32; 2]; +/// let x = array[0..].as_mut_ptr() as *mut [u32; 2]; // this is `array[0..2]` +/// let y = array[2..].as_mut_ptr() as *mut [u32; 2]; // this is `array[2..4]` /// /// unsafe { /// ptr::swap(x, y); @@ -130,11 +277,16 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } /// /// let mut array = [0, 1, 2, 3]; /// -/// let x = array[0..].as_mut_ptr() as *mut [u32; 3]; -/// let y = array[1..].as_mut_ptr() as *mut [u32; 3]; +/// let x = array[0..].as_mut_ptr() as *mut [u32; 3]; // this is `array[0..3]` +/// let y = array[1..].as_mut_ptr() as *mut [u32; 3]; // this is `array[1..4]` /// /// unsafe { /// ptr::swap(x, y); +/// // The indices `1..3` of the slice overlap between `x` and `y`. +/// // Reasonable results would be for to them be `[2, 3]`, so that indices `0..3` are +/// // `[1, 2, 3]` (matching `y` before the `swap`); or for them to be `[0, 1]` +/// // so that indices `1..4` are `[0, 1, 2]` (matching `x` before the `swap`). +/// // This implementation is defined to make the latter choice. /// assert_eq!([1, 0, 1, 2], array); /// } /// ``` @@ -154,12 +306,26 @@ pub unsafe fn swap(x: *mut T, y: *mut T) { mem::forget(tmp); } -/// Swaps a sequence of values at two mutable locations of the same type. +/// Swaps `count * size_of::()` bytes between the two regions of memory +/// beginning at `x` and `y`. The two regions must *not* overlap. /// /// # Safety /// -/// The two arguments must each point to the beginning of `count` locations -/// of valid memory, and the two memory ranges must not overlap. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * Both `x` and `y` must be [valid] for reads and writes of `count * +/// size_of::()` bytes. +/// +/// * Both `x` and `y` must be properly aligned. +/// +/// * The region of memory beginning at `x` with a size of `count * +/// size_of::()` bytes must *not* overlap with the region of memory +/// beginning at `y` with the same size. +/// +/// Note that even if the effectively copied size (`count * size_of::()`) is `0`, +/// the pointers must be non-NULL and properly aligned. +/// +/// [valid]: ../ptr/index.html#safety /// /// # Examples /// @@ -252,18 +418,48 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { } } -/// Moves `src` into the pointed `dest`, returning the previous `dest` value. +/// Moves `src` into the pointed `dst`, returning the previous `dst` value. /// /// Neither value is dropped. /// +/// This function is semantically equivalent to [`mem::replace`] except that it +/// operates on raw pointers instead of references. When references are +/// available, [`mem::replace`] should be preferred. +/// +/// [`mem::replace`]: ../mem/fn.replace.html +/// /// # Safety /// -/// This is only unsafe because it accepts a raw pointer. -/// Otherwise, this operation is identical to `mem::replace`. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dst` must be [valid] for writes. +/// +/// * `dst` must be properly aligned. +/// +/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// +/// [valid]: ../ptr/index.html#safety +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// let mut rust = vec!['b', 'u', 's', 't']; +/// +/// // `mem::replace` would have the same effect without requiring the unsafe +/// // block. +/// let b = unsafe { +/// ptr::replace(&mut rust[0], 'r') +/// }; +/// +/// assert_eq!(b, 'b'); +/// assert_eq!(rust, &['r', 'u', 's', 't']); +/// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn replace(dest: *mut T, mut src: T) -> T { - mem::swap(&mut *dest, &mut src); // cannot overlap +pub unsafe fn replace(dst: *mut T, mut src: T) -> T { + mem::swap(&mut *dst, &mut src); // cannot overlap src } @@ -272,14 +468,14 @@ pub unsafe fn replace(dest: *mut T, mut src: T) -> T { /// /// # Safety /// -/// Beyond accepting a raw pointer, this is unsafe because it semantically -/// moves the value out of `src` without preventing further usage of `src`. -/// If `T` is not `Copy`, then care must be taken to ensure that the value at -/// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use -/// because it will attempt to drop the value previously at `*src`. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must be [valid] for reads. +/// +/// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the +/// case. /// -/// The pointer must be aligned; use `read_unaligned` if that is not the case. +/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. /// /// # Examples /// @@ -293,6 +489,87 @@ pub unsafe fn replace(dest: *mut T, mut src: T) -> T { /// assert_eq!(std::ptr::read(y), 12); /// } /// ``` +/// +/// Manually implement [`mem::swap`]: +/// +/// ``` +/// use std::ptr; +/// +/// fn swap(a: &mut T, b: &mut T) { +/// unsafe { +/// // Create a bitwise copy of the value at `a` in `tmp`. +/// let tmp = ptr::read(a); +/// +/// // Exiting at this point (either by explicitly returning or by +/// // calling a function which panics) would cause the value in `tmp` to +/// // be dropped while the same value is still referenced by `a`. This +/// // could trigger undefined behavior if `T` is not `Copy`. +/// +/// // Create a bitwise copy of the value at `b` in `a`. +/// // This is safe because mutable references cannot alias. +/// ptr::copy_nonoverlapping(b, a, 1); +/// +/// // As above, exiting here could trigger undefined behavior because +/// // the same value is referenced by `a` and `b`. +/// +/// // Move `tmp` into `b`. +/// ptr::write(b, tmp); +/// +/// // `tmp` has been moved (`write` takes ownership of its second argument), +/// // so nothing is dropped implicitly here. +/// } +/// } +/// +/// let mut foo = "foo".to_owned(); +/// let mut bar = "bar".to_owned(); +/// +/// swap(&mut foo, &mut bar); +/// +/// assert_eq!(foo, "bar"); +/// assert_eq!(bar, "foo"); +/// ``` +/// +/// ## Ownership of the Returned Value +/// +/// `read` 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. Note that assigning to `*src` counts as a +/// use because it will attempt to drop the value at `*src`. +/// +/// [`write`] can be used to overwrite data without causing it to be dropped. +/// +/// ``` +/// use std::ptr; +/// +/// let mut s = String::from("foo"); +/// unsafe { +/// // `s2` now points to the same underlying memory as `s`. +/// let mut s2: String = ptr::read(&s); +/// +/// assert_eq!(s2, "foo"); +/// +/// // Assigning to `s2` causes its original value to be dropped. Beyond +/// // this point, `s` must no longer be used, as the underlying memory has +/// // been freed. +/// s2 = String::default(); +/// assert_eq!(s2, ""); +/// +/// // Assigning to `s` would cause the old value to be dropped again, +/// // resulting in undefined behavior. +/// // s = String::from("bar"); // ERROR +/// +/// // `ptr::write` can be used to overwrite a value without dropping it. +/// ptr::write(&mut s, String::from("bar")); +/// } +/// +/// assert_eq!(s, "bar"); +/// ``` +/// +/// [`mem::swap`]: ../mem/fn.swap.html +/// [valid]: ../ptr/index.html#safety +/// [`Copy`]: ../marker/trait.Copy.html +/// [`read_unaligned`]: ./fn.read_unaligned.html +/// [`write`]: ./fn.write.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn read(src: *const T) -> T { @@ -304,28 +581,61 @@ pub unsafe fn read(src: *const T) -> T { /// Reads the value from `src` without moving it. This leaves the /// memory in `src` unchanged. /// -/// Unlike `read`, the pointer may be unaligned. +/// Unlike [`read`], `read_unaligned` works with unaligned pointers. /// /// # Safety /// -/// Beyond accepting a raw pointer, this is unsafe because it semantically -/// moves the value out of `src` without preventing further usage of `src`. -/// If `T` is not `Copy`, then care must be taken to ensure that the value at -/// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use -/// because it will attempt to drop the value previously at `*src`. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must be [valid] for reads. +/// +/// Like [`read`], `read_unaligned` 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]. +/// +/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// +/// [`Copy`]: ../marker/trait.Copy.html +/// [`read`]: ./fn.read.html +/// [`write_unaligned`]: ./fn.write_unaligned.html +/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value +/// [valid]: ../ptr/index.html#safety /// /// # Examples /// -/// Basic usage: +/// Access members of a packed struct by reference: /// /// ``` -/// let x = 12; -/// let y = &x as *const i32; +/// use std::ptr; /// -/// unsafe { -/// assert_eq!(std::ptr::read_unaligned(y), 12); +/// #[repr(packed, C)] +/// struct Packed { +/// _padding: u8, +/// unaligned: u32, /// } +/// +/// let x = Packed { +/// _padding: 0x00, +/// unaligned: 0x01020304, +/// }; +/// +/// let v = unsafe { +/// // Take the address of a 32-bit integer which is not aligned. +/// // This must be done as a raw pointer; unaligned references are invalid. +/// let unaligned = &x.unaligned as *const u32; +/// +/// // Dereferencing normally will emit an aligned load instruction, +/// // causing undefined behavior. +/// // let v = *unaligned; // ERROR +/// +/// // Instead, use `read_unaligned` to read improperly aligned values. +/// let v = ptr::read_unaligned(unaligned); +/// +/// v +/// }; +/// +/// // Accessing unaligned values directly is safe. +/// assert!(x.unaligned == v); /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] @@ -340,21 +650,31 @@ pub unsafe fn read_unaligned(src: *const T) -> T { /// Overwrites a memory location with the given value without reading or /// dropping the old value. /// -/// # Safety -/// -/// This operation is marked unsafe because it accepts a raw pointer. -/// -/// It does not drop the contents of `dst`. This is safe, but it could leak -/// allocations or resources, so care must be taken not to overwrite an object +/// `write` 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. /// /// Additionally, it does not drop `src`. Semantically, `src` is moved into the /// location pointed to by `dst`. /// /// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been `read` from. +/// memory that has previously been [`read`] from. +/// +/// [`read`]: ./fn.read.html +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: /// -/// The pointer must be aligned; use `write_unaligned` if that is not the case. +/// * `dst` must be [valid] for writes. +/// +/// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the +/// case. +/// +/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// +/// [valid]: ../ptr/index.html#safety +/// [`write_unaligned`]: ./fn.write_unaligned.html /// /// # Examples /// @@ -370,6 +690,47 @@ pub unsafe fn read_unaligned(src: *const T) -> T { /// assert_eq!(std::ptr::read(y), 12); /// } /// ``` +/// +/// Manually implement [`mem::swap`]: +/// +/// ``` +/// use std::ptr; +/// +/// fn swap(a: &mut T, b: &mut T) { +/// unsafe { +/// // Create a bitwise copy of the value at `a` in `tmp`. +/// let tmp = ptr::read(a); +/// +/// // Exiting at this point (either by explicitly returning or by +/// // calling a function which panics) would cause the value in `tmp` to +/// // be dropped while the same value is still referenced by `a`. This +/// // could trigger undefined behavior if `T` is not `Copy`. +/// +/// // Create a bitwise copy of the value at `b` in `a`. +/// // This is safe because mutable references cannot alias. +/// ptr::copy_nonoverlapping(b, a, 1); +/// +/// // As above, exiting here could trigger undefined behavior because +/// // the same value is referenced by `a` and `b`. +/// +/// // Move `tmp` into `b`. +/// ptr::write(b, tmp); +/// +/// // `tmp` has been moved (`write` takes ownership of its second argument), +/// // so nothing is dropped implicitly here. +/// } +/// } +/// +/// let mut foo = "foo".to_owned(); +/// let mut bar = "bar".to_owned(); +/// +/// swap(&mut foo, &mut bar); +/// +/// assert_eq!(foo, "bar"); +/// assert_eq!(bar, "foo"); +/// ``` +/// +/// [`mem::swap`]: ../mem/fn.swap.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn write(dst: *mut T, src: T) { @@ -379,35 +740,62 @@ pub unsafe fn write(dst: *mut T, src: T) { /// Overwrites a memory location with the given value without reading or /// dropping the old value. /// -/// Unlike `write`, the pointer may be unaligned. -/// -/// # Safety -/// -/// This operation is marked unsafe because it accepts a raw pointer. +/// Unlike [`write`], the pointer may be unaligned. /// -/// It does not drop the contents of `dst`. This is safe, but it could leak -/// allocations or resources, so care must be taken not to overwrite an object -/// that should be dropped. +/// `write_unaligned` 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. /// /// Additionally, it does not drop `src`. Semantically, `src` is moved into the /// location pointed to by `dst`. /// /// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been `read` from. +/// memory that has previously been read with [`read_unaligned`]. +/// +/// [`write`]: ./fn.write.html +/// [`read_unaligned`]: ./fn.read_unaligned.html +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dst` must be [valid] for writes. +/// +/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// +/// [valid]: ../ptr/index.html#safety /// /// # Examples /// -/// Basic usage: +/// Access fields in a packed struct: /// /// ``` -/// let mut x = 0; -/// let y = &mut x as *mut i32; -/// let z = 12; +/// use std::{mem, ptr}; +/// +/// #[repr(packed, C)] +/// #[derive(Default)] +/// struct Packed { +/// _padding: u8, +/// unaligned: u32, +/// } +/// +/// let v = 0x01020304; +/// let mut x: Packed = unsafe { mem::zeroed() }; /// /// unsafe { -/// std::ptr::write_unaligned(y, z); -/// assert_eq!(std::ptr::read_unaligned(y), 12); +/// // Take a reference to a 32-bit integer which is not aligned. +/// let unaligned = &mut x.unaligned as *mut u32; +/// +/// // Dereferencing normally will emit an aligned store instruction, +/// // causing undefined behavior because the pointer is not aligned. +/// // *unaligned = v; // ERROR +/// +/// // Instead, use `write_unaligned` to write improperly aligned values. +/// ptr::write_unaligned(unaligned, v); /// } +/// +/// // Accessing unaligned values directly is safe. +/// assert!(x.unaligned == v); /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] @@ -425,6 +813,11 @@ pub unsafe fn write_unaligned(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 /// /// Rust does not currently have a rigorously and formally defined memory model, @@ -441,12 +834,23 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { /// /// # Safety /// -/// Beyond accepting a raw pointer, this is unsafe because it semantically -/// moves the value out of `src` without preventing further usage of `src`. -/// If `T` is not `Copy`, then care must be taken to ensure that the value at -/// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use -/// because it will attempt to drop the value previously at `*src`. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must be [valid] for reads. +/// +/// * `src` must be properly aligned. +/// +/// Like [`read`], `read_unaligned` 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 +/// incorrect. +/// +/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// +/// [valid]: ../ptr/index.html#safety +/// [`Copy`]: ../marker/trait.Copy.html +/// [`read`]: ./fn.read.html /// /// Just like in C, whether an operation is volatile has no bearing whatsoever /// on questions involving concurrent access from multiple threads. Volatile @@ -479,6 +883,18 @@ pub unsafe fn read_volatile(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. +/// +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. +/// +/// [`read_volatile`]: ./fn.read_volatile.html +/// /// # Notes /// /// Rust does not currently have a rigorously and formally defined memory model, @@ -495,14 +911,15 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// /// # Safety /// -/// This operation is marked unsafe because it accepts a raw pointer. +/// Behavior is undefined if any of the following conditions are violated: /// -/// It does not drop the contents of `dst`. This is safe, but it could leak -/// allocations or resources, so care must be taken not to overwrite an object -/// that should be dropped. +/// * `dst` must be [valid] for writes. /// -/// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been `read` from. +/// * `dst` must be properly aligned. +/// +/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// +/// [valid]: ../ptr/index.html#safety /// /// Just like in C, whether an operation is volatile has no bearing whatsoever /// on questions involving concurrent access from multiple threads. Volatile @@ -1023,29 +1440,9 @@ impl *const T { /// Reads the value from `self` without moving it. This leaves the /// memory in `self` unchanged. /// - /// # Safety + /// See [`ptr::read`] for safety concerns and examples. /// - /// Beyond accepting a raw pointer, this is unsafe because it semantically - /// moves the value out of `self` without preventing further usage of `self`. - /// If `T` is not `Copy`, then care must be taken to ensure that the value at - /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use - /// because it will attempt to drop the value previously at `*self`. - /// - /// The pointer must be aligned; use `read_unaligned` if that is not the case. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let x = 12; - /// let y = &x as *const i32; - /// - /// unsafe { - /// assert_eq!(y.read(), 12); - /// } - /// ``` + /// [`ptr::read`]: ./ptr/fn.read.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read(self) -> T @@ -1061,47 +1458,9 @@ impl *const T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// - /// # Notes - /// - /// Rust does not currently have a rigorously and formally defined memory model, - /// so the precise semantics of what "volatile" means here is subject to change - /// over time. That being said, the semantics will almost always end up pretty - /// similar to [C11's definition of volatile][c11]. - /// - /// The compiler shouldn't change the relative order or number of volatile - /// memory operations. However, volatile memory operations on zero-sized types - /// (e.g. if a zero-sized type is passed to `read_volatile`) are no-ops - /// and may be ignored. - /// - /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf - /// - /// # Safety - /// - /// Beyond accepting a raw pointer, this is unsafe because it semantically - /// moves the value out of `self` without preventing further usage of `self`. - /// If `T` is not `Copy`, then care must be taken to ensure that the value at - /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use - /// because it will attempt to drop the value previously at `*self`. + /// See [`ptr::read_volatile`] for safety concerns and examples. /// - /// Just like in C, whether an operation is volatile has no bearing whatsoever - /// on questions involving concurrent access from multiple threads. Volatile - /// accesses behave exactly like non-atomic accesses in that regard. In particular, - /// a race between a `read_volatile` and any write operation to the same location - /// is undefined behavior. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let x = 12; - /// let y = &x as *const i32; - /// - /// unsafe { - /// assert_eq!(y.read_volatile(), 12); - /// } - /// ``` + /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read_volatile(self) -> T @@ -1115,27 +1474,9 @@ impl *const T { /// /// Unlike `read`, the pointer may be unaligned. /// - /// # Safety - /// - /// Beyond accepting a raw pointer, this is unsafe because it semantically - /// moves the value out of `self` without preventing further usage of `self`. - /// If `T` is not `Copy`, then care must be taken to ensure that the value at - /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use - /// because it will attempt to drop the value previously at `*self`. + /// See [`ptr::read_unaligned`] for safety concerns and examples. /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let x = 12; - /// let y = &x as *const i32; - /// - /// unsafe { - /// assert_eq!(y.read_unaligned(), 12); - /// } - /// ``` + /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read_unaligned(self) -> T @@ -1147,30 +1488,11 @@ impl *const T { /// Copies `count * size_of` bytes from `self` to `dest`. The source /// and destination may overlap. /// - /// NOTE: this has the *same* argument order as `ptr::copy`. - /// - /// This is semantically equivalent to C's `memmove`. - /// - /// # Safety + /// NOTE: this has the *same* argument order as [`ptr::copy`]. /// - /// Care must be taken with the ownership of `self` and `dest`. - /// This method semantically moves the values of `self` into `dest`. - /// However it does not drop the contents of `dest`, or prevent the contents - /// of `self` from being dropped or used. + /// See [`ptr::copy`] for safety concerns and examples. /// - /// # Examples - /// - /// Efficiently create a Rust vector from an unsafe buffer: - /// - /// ``` - /// # #[allow(dead_code)] - /// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { - /// let mut dst = Vec::with_capacity(elts); - /// dst.set_len(elts); - /// ptr.copy_to(dst.as_mut_ptr(), elts); - /// dst - /// } - /// ``` + /// [`ptr::copy`]: ./ptr/fn.copy.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_to(self, dest: *mut T, count: usize) @@ -1182,32 +1504,11 @@ impl *const T { /// Copies `count * size_of` bytes from `self` to `dest`. The source /// and destination may *not* overlap. /// - /// NOTE: this has the *same* argument order as `ptr::copy_nonoverlapping`. + /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`]. /// - /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`. - /// - /// # Safety - /// - /// Beyond requiring that the program must be allowed to access both regions - /// of memory, it is Undefined Behavior for source and destination to - /// overlap. Care must also be taken with the ownership of `self` and - /// `self`. This method semantically moves the values of `self` into `dest`. - /// However it does not drop the contents of `dest`, or prevent the contents - /// of `self` from being dropped or used. - /// - /// # Examples + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// - /// Efficiently create a Rust vector from an unsafe buffer: - /// - /// ``` - /// # #[allow(dead_code)] - /// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { - /// let mut dst = Vec::with_capacity(elts); - /// dst.set_len(elts); - /// ptr.copy_to_nonoverlapping(dst.as_mut_ptr(), elts); - /// dst - /// } - /// ``` + /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize) @@ -1777,29 +2078,9 @@ impl *mut T { /// Reads the value from `self` without moving it. This leaves the /// memory in `self` unchanged. /// - /// # Safety - /// - /// Beyond accepting a raw pointer, this is unsafe because it semantically - /// moves the value out of `self` without preventing further usage of `self`. - /// If `T` is not `Copy`, then care must be taken to ensure that the value at - /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use - /// because it will attempt to drop the value previously at `*self`. + /// See [`ptr::read`] for safety concerns and examples. /// - /// The pointer must be aligned; use `read_unaligned` if that is not the case. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let x = 12; - /// let y = &x as *const i32; - /// - /// unsafe { - /// assert_eq!(y.read(), 12); - /// } - /// ``` + /// [`ptr::read`]: ./ptr/fn.read.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read(self) -> T @@ -1815,47 +2096,9 @@ impl *mut T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// - /// # Notes - /// - /// Rust does not currently have a rigorously and formally defined memory model, - /// so the precise semantics of what "volatile" means here is subject to change - /// over time. That being said, the semantics will almost always end up pretty - /// similar to [C11's definition of volatile][c11]. - /// - /// The compiler shouldn't change the relative order or number of volatile - /// memory operations. However, volatile memory operations on zero-sized types - /// (e.g. if a zero-sized type is passed to `read_volatile`) are no-ops - /// and may be ignored. - /// - /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf - /// - /// # Safety - /// - /// Beyond accepting a raw pointer, this is unsafe because it semantically - /// moves the value out of `self` without preventing further usage of `self`. - /// If `T` is not `Copy`, then care must be taken to ensure that the value at - /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use - /// because it will attempt to drop the value previously at `*self`. - /// - /// Just like in C, whether an operation is volatile has no bearing whatsoever - /// on questions involving concurrent access from multiple threads. Volatile - /// accesses behave exactly like non-atomic accesses in that regard. In particular, - /// a race between a `read_volatile` and any write operation to the same location - /// is undefined behavior. + /// See [`ptr::read_volatile`] for safety concerns and examples. /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let x = 12; - /// let y = &x as *const i32; - /// - /// unsafe { - /// assert_eq!(y.read_volatile(), 12); - /// } - /// ``` + /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read_volatile(self) -> T @@ -1869,27 +2112,9 @@ impl *mut T { /// /// Unlike `read`, the pointer may be unaligned. /// - /// # Safety - /// - /// Beyond accepting a raw pointer, this is unsafe because it semantically - /// moves the value out of `self` without preventing further usage of `self`. - /// If `T` is not `Copy`, then care must be taken to ensure that the value at - /// `self` is not used before the data is overwritten again (e.g. with `write`, - /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use - /// because it will attempt to drop the value previously at `*self`. + /// See [`ptr::read_unaligned`] for safety concerns and examples. /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let x = 12; - /// let y = &x as *const i32; - /// - /// unsafe { - /// assert_eq!(y.read_unaligned(), 12); - /// } - /// ``` + /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read_unaligned(self) -> T @@ -1901,30 +2126,11 @@ impl *mut T { /// Copies `count * size_of` bytes from `self` to `dest`. The source /// and destination may overlap. /// - /// NOTE: this has the *same* argument order as `ptr::copy`. - /// - /// This is semantically equivalent to C's `memmove`. - /// - /// # Safety + /// NOTE: this has the *same* argument order as [`ptr::copy`]. /// - /// Care must be taken with the ownership of `self` and `dest`. - /// This method semantically moves the values of `self` into `dest`. - /// However it does not drop the contents of `self`, or prevent the contents - /// of `dest` from being dropped or used. + /// See [`ptr::copy`] for safety concerns and examples. /// - /// # Examples - /// - /// Efficiently create a Rust vector from an unsafe buffer: - /// - /// ``` - /// # #[allow(dead_code)] - /// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { - /// let mut dst = Vec::with_capacity(elts); - /// dst.set_len(elts); - /// ptr.copy_to(dst.as_mut_ptr(), elts); - /// dst - /// } - /// ``` + /// [`ptr::copy`]: ./ptr/fn.copy.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_to(self, dest: *mut T, count: usize) @@ -1936,32 +2142,11 @@ impl *mut T { /// Copies `count * size_of` bytes from `self` to `dest`. The source /// and destination may *not* overlap. /// - /// NOTE: this has the *same* argument order as `ptr::copy_nonoverlapping`. - /// - /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`. - /// - /// # Safety - /// - /// Beyond requiring that the program must be allowed to access both regions - /// of memory, it is Undefined Behavior for source and destination to - /// overlap. Care must also be taken with the ownership of `self` and - /// `self`. This method semantically moves the values of `self` into `dest`. - /// However it does not drop the contents of `dest`, or prevent the contents - /// of `self` from being dropped or used. - /// - /// # Examples + /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`]. /// - /// Efficiently create a Rust vector from an unsafe buffer: + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// - /// ``` - /// # #[allow(dead_code)] - /// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { - /// let mut dst = Vec::with_capacity(elts); - /// dst.set_len(elts); - /// ptr.copy_to_nonoverlapping(dst.as_mut_ptr(), elts); - /// dst - /// } - /// ``` + /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize) @@ -1973,30 +2158,11 @@ impl *mut T { /// Copies `count * size_of` bytes from `src` to `self`. The source /// and destination may overlap. /// - /// NOTE: this has the *opposite* argument order of `ptr::copy`. - /// - /// This is semantically equivalent to C's `memmove`. - /// - /// # Safety + /// NOTE: this has the *opposite* argument order of [`ptr::copy`]. /// - /// Care must be taken with the ownership of `src` and `self`. - /// This method semantically moves the values of `src` into `self`. - /// However it does not drop the contents of `self`, or prevent the contents - /// of `src` from being dropped or used. + /// See [`ptr::copy`] for safety concerns and examples. /// - /// # Examples - /// - /// Efficiently create a Rust vector from an unsafe buffer: - /// - /// ``` - /// # #[allow(dead_code)] - /// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { - /// let mut dst: Vec = Vec::with_capacity(elts); - /// dst.set_len(elts); - /// dst.as_mut_ptr().copy_from(ptr, elts); - /// dst - /// } - /// ``` + /// [`ptr::copy`]: ./ptr/fn.copy.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_from(self, src: *const T, count: usize) @@ -2008,32 +2174,11 @@ impl *mut T { /// Copies `count * size_of` bytes from `src` to `self`. The source /// and destination may *not* overlap. /// - /// NOTE: this has the *opposite* argument order of `ptr::copy_nonoverlapping`. - /// - /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`. - /// - /// # Safety - /// - /// Beyond requiring that the program must be allowed to access both regions - /// of memory, it is Undefined Behavior for source and destination to - /// overlap. Care must also be taken with the ownership of `src` and - /// `self`. This method semantically moves the values of `src` into `self`. - /// However it does not drop the contents of `self`, or prevent the contents - /// of `src` from being dropped or used. - /// - /// # Examples + /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`]. /// - /// Efficiently create a Rust vector from an unsafe buffer: + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// - /// ``` - /// # #[allow(dead_code)] - /// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { - /// let mut dst: Vec = Vec::with_capacity(elts); - /// dst.set_len(elts); - /// dst.as_mut_ptr().copy_from_nonoverlapping(ptr, elts); - /// dst - /// } - /// ``` + /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize) @@ -2044,21 +2189,9 @@ impl *mut T { /// Executes the destructor (if any) of the pointed-to value. /// - /// This has two use cases: - /// - /// * It is *required* to use `drop_in_place` to drop unsized types like - /// trait objects, because they can't be read out onto the stack and - /// dropped normally. - /// - /// * It is friendlier to the optimizer to do this over `ptr::read` when - /// dropping manually allocated memory (e.g. when writing Box/Rc/Vec), - /// as the compiler doesn't need to prove that it's sound to elide the - /// copy. + /// See [`ptr::drop_in_place`] for safety concerns and examples. /// - /// # Safety - /// - /// This has all the same safety problems as `ptr::read` with respect to - /// invalid pointers, types, and double drops. + /// [`ptr::drop_in_place`]: ./ptr/fn.drop_in_place.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn drop_in_place(self) { @@ -2068,36 +2201,9 @@ impl *mut T { /// Overwrites a memory location with the given value without reading or /// dropping the old value. /// - /// # Safety - /// - /// This operation is marked unsafe because it writes through a raw pointer. - /// - /// It does not drop the contents of `self`. This is safe, but it could leak - /// allocations or resources, so care must be taken not to overwrite an object - /// that should be dropped. - /// - /// Additionally, it does not drop `val`. Semantically, `val` is moved into the - /// location pointed to by `self`. - /// - /// This is appropriate for initializing uninitialized memory, or overwriting - /// memory that has previously been `read` from. - /// - /// The pointer must be aligned; use `write_unaligned` if that is not the case. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut x = 0; - /// let y = &mut x as *mut i32; - /// let z = 12; + /// See [`ptr::write`] for safety concerns and examples. /// - /// unsafe { - /// y.write(z); - /// assert_eq!(y.read(), 12); - /// } - /// ``` + /// [`ptr::write`]: ./ptr/fn.write.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn write(self, val: T) @@ -2109,16 +2215,9 @@ impl *mut T { /// Invokes memset on the specified pointer, setting `count * size_of::()` /// bytes of memory starting at `self` to `val`. /// - /// # Examples + /// See [`ptr::write_bytes`] for safety concerns and examples. /// - /// ``` - /// let mut vec = vec![0; 4]; - /// unsafe { - /// let vec_ptr = vec.as_mut_ptr(); - /// vec_ptr.write_bytes(b'a', 2); - /// } - /// assert_eq!(vec, [b'a', b'a', 0, 0]); - /// ``` + /// [`ptr::write_bytes`]: ./ptr/fn.write_bytes.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn write_bytes(self, val: u8, count: usize) @@ -2134,51 +2233,9 @@ impl *mut T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// - /// # Notes - /// - /// Rust does not currently have a rigorously and formally defined memory model, - /// so the precise semantics of what "volatile" means here is subject to change - /// over time. That being said, the semantics will almost always end up pretty - /// similar to [C11's definition of volatile][c11]. - /// - /// The compiler shouldn't change the relative order or number of volatile - /// memory operations. However, volatile memory operations on zero-sized types - /// (e.g. if a zero-sized type is passed to `write_volatile`) are no-ops - /// and may be ignored. - /// - /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf - /// - /// # Safety - /// - /// This operation is marked unsafe because it accepts a raw pointer. - /// - /// It does not drop the contents of `self`. This is safe, but it could leak - /// allocations or resources, so care must be taken not to overwrite an object - /// that should be dropped. - /// - /// This is appropriate for initializing uninitialized memory, or overwriting - /// memory that has previously been `read` from. - /// - /// Just like in C, whether an operation is volatile has no bearing whatsoever - /// on questions involving concurrent access from multiple threads. Volatile - /// accesses behave exactly like non-atomic accesses in that regard. In particular, - /// a race between a `write_volatile` and any other operation (reading or writing) - /// on the same location is undefined behavior. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut x = 0; - /// let y = &mut x as *mut i32; - /// let z = 12; + /// See [`ptr::write_volatile`] for safety concerns and examples. /// - /// unsafe { - /// y.write_volatile(z); - /// assert_eq!(y.read_volatile(), 12); - /// } - /// ``` + /// [`ptr::write_volatile`]: ./ptr/fn.write_volatile.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn write_volatile(self, val: T) @@ -2192,34 +2249,9 @@ impl *mut T { /// /// Unlike `write`, the pointer may be unaligned. /// - /// # Safety - /// - /// This operation is marked unsafe because it writes through a raw pointer. - /// - /// It does not drop the contents of `self`. This is safe, but it could leak - /// allocations or resources, so care must be taken not to overwrite an object - /// that should be dropped. + /// See [`ptr::write_unaligned`] for safety concerns and examples. /// - /// Additionally, it does not drop `self`. Semantically, `self` is moved into the - /// location pointed to by `val`. - /// - /// This is appropriate for initializing uninitialized memory, or overwriting - /// memory that has previously been `read` from. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut x = 0; - /// let y = &mut x as *mut i32; - /// let z = 12; - /// - /// unsafe { - /// y.write_unaligned(z); - /// assert_eq!(y.read_unaligned(), 12); - /// } - /// ``` + /// [`ptr::write_unaligned`]: ./ptr/fn.write_unaligned.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn write_unaligned(self, val: T) @@ -2231,10 +2263,9 @@ impl *mut T { /// Replaces the value at `self` with `src`, returning the old /// value, without dropping either. /// - /// # Safety + /// See [`ptr::replace`] for safety concerns and examples. /// - /// This is only unsafe because it accepts a raw pointer. - /// Otherwise, this operation is identical to `mem::replace`. + /// [`ptr::replace`]: ./ptr/fn.replace.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn replace(self, src: T) -> T @@ -2247,12 +2278,9 @@ impl *mut T { /// deinitializing either. They may overlap, unlike `mem::swap` which is /// otherwise equivalent. /// - /// # Safety - /// - /// This function copies the memory through the raw pointers passed to it - /// as arguments. + /// See [`ptr::swap`] for safety concerns and examples. /// - /// Ensure that these pointers are valid before calling `swap`. + /// [`ptr::swap`]: ./ptr/fn.swap.html #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn swap(self, with: *mut T)