@@ -962,59 +962,127 @@ extern "rust-intrinsic" {
962962 /// value is not necessarily valid to be used to actually access memory.
963963 pub fn arith_offset < T > ( dst : * const T , offset : isize ) -> * const T ;
964964
965- /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
966- /// and destination may *not* overlap.
965+ /// Copies `count * size_of:: <T>() ` bytes from `src` to `dst`. The source
966+ /// and destination must *not* overlap.
967967 ///
968- /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`.
968+ /// For regions of memory which might overlap, use [`copy`] instead.
969+ ///
970+ /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
971+ /// with the argument order swapped.
972+ ///
973+ /// [`copy`]: ./fn.copy.html
974+ /// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
969975 ///
970976 /// # Safety
971977 ///
972- /// Beyond requiring that the program must be allowed to access both regions
973- /// of memory, it is Undefined Behavior for source and destination to
974- /// overlap. Care must also be taken with the ownership of `src` and
975- /// `dst`. This method semantically moves the values of `src` into `dst`.
976- /// However it does not drop the contents of `dst`, or prevent the contents
977- /// of `src` from being dropped or used.
978+ /// Behavior is undefined if any of the following conditions are violated:
979+ ///
980+ /// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
981+ ///
982+ /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
983+ ///
984+ /// * Both `src` and `dst` must be properly aligned.
985+ ///
986+ /// * The region of memory beginning at `src` with a size of `count *
987+ /// size_of::<T>()` bytes must *not* overlap with the region of memory
988+ /// beginning at `dst` with the same size.
989+ ///
990+ /// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
991+ /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
992+ /// in the region beginning at `*src` and the region beginning at `*dst` can
993+ /// [violate memory safety][read-ownership].
994+ ///
995+ /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
996+ /// `0`, the pointers must be non-NULL and properly aligned.
997+ ///
998+ /// [`Copy`]: ../marker/trait.Copy.html
999+ /// [`read`]: ../ptr/fn.read.html
1000+ /// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
1001+ /// [valid]: ../ptr/index.html#safety
9781002 ///
9791003 /// # Examples
9801004 ///
981- /// A safe swap function :
1005+ /// Manually implement [`Vec::append`] :
9821006 ///
9831007 /// ```
984- /// use std::mem;
9851008 /// use std::ptr;
9861009 ///
987- /// # #[allow(dead_code)]
988- /// fn swap<T>(x: &mut T, y: &mut T) {
989- /// unsafe {
990- /// // Give ourselves some scratch space to work with
991- /// let mut t: T = mem::uninitialized();
1010+ /// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
1011+ /// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
1012+ /// let src_len = src.len();
1013+ /// let dst_len = dst.len();
9921014 ///
993- /// // Perform the swap, `&mut` pointers never alias
994- /// ptr::copy_nonoverlapping(x, &mut t, 1);
995- /// ptr::copy_nonoverlapping(y, x, 1);
996- /// ptr::copy_nonoverlapping(&t, y, 1);
1015+ /// // Ensure that `dst` has enough capacity to hold all of `src`.
1016+ /// dst.reserve(src_len);
9971017 ///
998- /// // y and t now point to the same thing, but we need to completely forget `t`
999- /// // because it's no longer relevant.
1000- /// mem::forget(t);
1018+ /// unsafe {
1019+ /// // The call to offset is always safe because `Vec` will never
1020+ /// // allocate more than `isize::MAX` bytes.
1021+ /// let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
1022+ /// let src_ptr = src.as_ptr();
1023+ ///
1024+ /// // Truncate `src` without dropping its contents. We do this first,
1025+ /// // to avoid problems in case something further down panics.
1026+ /// src.set_len(0);
1027+ ///
1028+ /// // The two regions cannot overlap becuase mutable references do
1029+ /// // not alias, and two different vectors cannot own the same
1030+ /// // memory.
1031+ /// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
1032+ ///
1033+ /// // Notify `dst` that it now holds the contents of `src`.
1034+ /// dst.set_len(dst_len + src_len);
10011035 /// }
10021036 /// }
1037+ ///
1038+ /// let mut a = vec!['r'];
1039+ /// let mut b = vec!['u', 's', 't'];
1040+ ///
1041+ /// append(&mut a, &mut b);
1042+ ///
1043+ /// assert_eq!(a, &['r', 'u', 's', 't']);
1044+ /// assert!(b.is_empty());
10031045 /// ```
1046+ ///
1047+ /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
10041048 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
10051049 pub fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) ;
10061050
1007- /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
1051+ /// Copies `count * size_of:: <T>() ` bytes from `src` to `dst`. The source
10081052 /// and destination may overlap.
10091053 ///
1010- /// `copy` is semantically equivalent to C's `memmove`.
1054+ /// If the source and destination will *never* overlap,
1055+ /// [`copy_nonoverlapping`] can be used instead.
1056+ ///
1057+ /// `copy` is semantically equivalent to C's [`memmove`], but with the argument
1058+ /// order swapped. Copying takes place as if the bytes were copied from `src`
1059+ /// to a temporary array and then copied from the array to `dst`.
1060+ ///
1061+ /// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html
1062+ /// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
10111063 ///
10121064 /// # Safety
10131065 ///
1014- /// Care must be taken with the ownership of `src` and `dst`.
1015- /// This method semantically moves the values of `src` into `dst`.
1016- /// However it does not drop the contents of `dst`, or prevent the contents of `src`
1017- /// from being dropped or used.
1066+ /// Behavior is undefined if any of the following conditions are violated:
1067+ ///
1068+ /// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
1069+ ///
1070+ /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
1071+ ///
1072+ /// * Both `src` and `dst` must be properly aligned.
1073+ ///
1074+ /// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
1075+ /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
1076+ /// in the region beginning at `*src` and the region beginning at `*dst` can
1077+ /// [violate memory safety][read-ownership].
1078+ ///
1079+ /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
1080+ /// `0`, the pointers must be non-NULL and properly aligned.
1081+ ///
1082+ /// [`Copy`]: ../marker/trait.Copy.html
1083+ /// [`read`]: ../ptr/fn.read.html
1084+ /// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
1085+ /// [valid]: ../ptr/index.html#safety
10181086 ///
10191087 /// # Examples
10201088 ///
@@ -1031,24 +1099,80 @@ extern "rust-intrinsic" {
10311099 /// dst
10321100 /// }
10331101 /// ```
1034- ///
10351102 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
10361103 pub fn copy < T > ( src : * const T , dst : * mut T , count : usize ) ;
10371104
1038- /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
1039- /// bytes of memory starting at `dst` to `val`.
1105+ /// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
1106+ /// `val`.
1107+ ///
1108+ /// `write_bytes` is similar to C's [`memset`], but sets `count *
1109+ /// size_of::<T>()` bytes to `val`.
1110+ ///
1111+ /// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset
1112+ ///
1113+ /// # Safety
1114+ ///
1115+ /// Behavior is undefined if any of the following conditions are violated:
1116+ ///
1117+ /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
1118+ ///
1119+ /// * `dst` must be properly aligned.
1120+ ///
1121+ /// Additionally, the caller must ensure that writing `count *
1122+ /// size_of::<T>()` bytes to the given region of memory results in a valid
1123+ /// value of `T`. Using a region of memory typed as a `T` that contains an
1124+ /// invalid value of `T` is undefined behavior.
1125+ ///
1126+ /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
1127+ /// `0`, the pointer must be non-NULL and properly aligned.
1128+ ///
1129+ /// [valid]: ../ptr/index.html#safety
10401130 ///
10411131 /// # Examples
10421132 ///
1133+ /// Basic usage:
1134+ ///
10431135 /// ```
10441136 /// use std::ptr;
10451137 ///
1046- /// let mut vec = vec![0 ; 4];
1138+ /// let mut vec = vec![0u32 ; 4];
10471139 /// unsafe {
10481140 /// let vec_ptr = vec.as_mut_ptr();
1049- /// ptr::write_bytes(vec_ptr, b'a', 2);
1141+ /// ptr::write_bytes(vec_ptr, 0xfe, 2);
1142+ /// }
1143+ /// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]);
1144+ /// ```
1145+ ///
1146+ /// Creating an invalid value:
1147+ ///
1148+ /// ```
1149+ /// use std::ptr;
1150+ ///
1151+ /// let mut v = Box::new(0i32);
1152+ ///
1153+ /// unsafe {
1154+ /// // Leaks the previously held value by overwriting the `Box<T>` with
1155+ /// // a null pointer.
1156+ /// ptr::write_bytes(&mut v as *mut Box<i32>, 0, 1);
10501157 /// }
1051- /// assert_eq!(vec, [b'a', b'a', 0, 0]);
1158+ ///
1159+ /// // At this point, using or dropping `v` results in undefined behavior.
1160+ /// // drop(v); // ERROR
1161+ ///
1162+ /// // Even leaking `v` "uses" it, and hence is undefined behavior.
1163+ /// // mem::forget(v); // ERROR
1164+ ///
1165+ /// // In fact, `v` is invalid according to basic type layout invariants, so *any*
1166+ /// // operation touching it is undefined behavior.
1167+ /// // let v2 = v; // ERROR
1168+ ///
1169+ /// unsafe {
1170+ /// // Let us instead put in a valid value
1171+ /// ptr::write(&mut v as *mut Box<i32>, Box::new(42i32));
1172+ /// }
1173+ ///
1174+ /// // Now the box is fine
1175+ /// assert_eq!(*v, 42);
10521176 /// ```
10531177 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
10541178 pub fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) ;
@@ -1066,7 +1190,7 @@ extern "rust-intrinsic" {
10661190 /// `min_align_of::<T>()`
10671191 ///
10681192 /// The volatile parameter is set to `true`, so it will not be optimized out
1069- /// unless size is equal to zero..
1193+ /// unless size is equal to zero.
10701194 pub fn volatile_copy_memory < T > ( dst : * mut T , src : * const T , count : usize ) ;
10711195 /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
10721196 /// size of `count` * `size_of::<T>()` and an alignment of
0 commit comments