Skip to content

Commit 168bac1

Browse files
committed
Wrap write_bytes in a function. Move docs
This will allow us to add debug assertions. See issue #53871.
1 parent c325155 commit 168bac1

File tree

2 files changed

+75
-73
lines changed

2 files changed

+75
-73
lines changed

src/libcore/intrinsics.rs

-72
Original file line numberDiff line numberDiff line change
@@ -1102,78 +1102,6 @@ extern "rust-intrinsic" {
11021102
#[stable(feature = "rust1", since = "1.0.0")]
11031103
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
11041104

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
1130-
///
1131-
/// # Examples
1132-
///
1133-
/// Basic usage:
1134-
///
1135-
/// ```
1136-
/// use std::ptr;
1137-
///
1138-
/// let mut vec = vec![0u32; 4];
1139-
/// unsafe {
1140-
/// let vec_ptr = vec.as_mut_ptr();
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);
1157-
/// }
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);
1176-
/// ```
11771105
#[stable(feature = "rust1", since = "1.0.0")]
11781106
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
11791107

src/libcore/ptr.rs

+75-1
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,82 @@ pub use intrinsics::copy_nonoverlapping;
7979
#[stable(feature = "rust1", since = "1.0.0")]
8080
pub use intrinsics::copy;
8181

82+
/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
83+
/// `val`.
84+
///
85+
/// `write_bytes` is similar to C's [`memset`], but sets `count *
86+
/// size_of::<T>()` bytes to `val`.
87+
///
88+
/// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset
89+
///
90+
/// # Safety
91+
///
92+
/// Behavior is undefined if any of the following conditions are violated:
93+
///
94+
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
95+
///
96+
/// * `dst` must be properly aligned.
97+
///
98+
/// Additionally, the caller must ensure that writing `count *
99+
/// size_of::<T>()` bytes to the given region of memory results in a valid
100+
/// value of `T`. Using a region of memory typed as a `T` that contains an
101+
/// invalid value of `T` is undefined behavior.
102+
///
103+
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
104+
/// `0`, the pointer must be non-NULL and properly aligned.
105+
///
106+
/// [valid]: ../ptr/index.html#safety
107+
///
108+
/// # Examples
109+
///
110+
/// Basic usage:
111+
///
112+
/// ```
113+
/// use std::ptr;
114+
///
115+
/// let mut vec = vec![0u32; 4];
116+
/// unsafe {
117+
/// let vec_ptr = vec.as_mut_ptr();
118+
/// ptr::write_bytes(vec_ptr, 0xfe, 2);
119+
/// }
120+
/// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]);
121+
/// ```
122+
///
123+
/// Creating an invalid value:
124+
///
125+
/// ```
126+
/// use std::ptr;
127+
///
128+
/// let mut v = Box::new(0i32);
129+
///
130+
/// unsafe {
131+
/// // Leaks the previously held value by overwriting the `Box<T>` with
132+
/// // a null pointer.
133+
/// ptr::write_bytes(&mut v as *mut Box<i32>, 0, 1);
134+
/// }
135+
///
136+
/// // At this point, using or dropping `v` results in undefined behavior.
137+
/// // drop(v); // ERROR
138+
///
139+
/// // Even leaking `v` "uses" it, and hence is undefined behavior.
140+
/// // mem::forget(v); // ERROR
141+
///
142+
/// // In fact, `v` is invalid according to basic type layout invariants, so *any*
143+
/// // operation touching it is undefined behavior.
144+
/// // let v2 = v; // ERROR
145+
///
146+
/// unsafe {
147+
/// // Let us instead put in a valid value
148+
/// ptr::write(&mut v as *mut Box<i32>, Box::new(42i32));
149+
/// }
150+
///
151+
/// // Now the box is fine
152+
/// assert_eq!(*v, 42);
153+
/// ```
82154
#[stable(feature = "rust1", since = "1.0.0")]
83-
pub use intrinsics::write_bytes;
155+
pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
156+
intrinsics::write_bytes(dst, val, count);
157+
}
84158

85159
/// Executes the destructor (if any) of the pointed-to value.
86160
///

0 commit comments

Comments
 (0)