1 | use crate::any::type_name; |
2 | use crate::fmt; |
3 | use crate::intrinsics; |
4 | use crate::mem::{self, ManuallyDrop}; |
5 | use crate::ptr; |
6 | use crate::slice; |
7 | |
8 | /// A wrapper type to construct uninitialized instances of `T`. |
9 | /// |
10 | /// # Initialization invariant |
11 | /// |
12 | /// The compiler, in general, assumes that a variable is properly initialized |
13 | /// according to the requirements of the variable's type. For example, a variable of |
14 | /// reference type must be aligned and non-null. This is an invariant that must |
15 | /// *always* be upheld, even in unsafe code. As a consequence, zero-initializing a |
16 | /// variable of reference type causes instantaneous [undefined behavior][ub], |
17 | /// no matter whether that reference ever gets used to access memory: |
18 | /// |
19 | /// ```rust,no_run |
20 | /// # #![allow (invalid_value)] |
21 | /// use std::mem::{self, MaybeUninit}; |
22 | /// |
23 | /// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! ⚠️ |
24 | /// // The equivalent code with `MaybeUninit<&i32>`: |
25 | /// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! ⚠️ |
26 | /// ``` |
27 | /// |
28 | /// This is exploited by the compiler for various optimizations, such as eliding |
29 | /// run-time checks and optimizing `enum` layout. |
30 | /// |
31 | /// Similarly, entirely uninitialized memory may have any content, while a `bool` must |
32 | /// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: |
33 | /// |
34 | /// ```rust,no_run |
35 | /// # #![allow(invalid_value)] |
36 | /// use std::mem::{self, MaybeUninit}; |
37 | /// |
38 | /// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ |
39 | /// // The equivalent code with `MaybeUninit<bool>`: |
40 | /// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ |
41 | /// ``` |
42 | /// |
43 | /// Moreover, uninitialized memory is special in that it does not have a fixed value ("fixed" |
44 | /// meaning "it won't change without being written to"). Reading the same uninitialized byte |
45 | /// multiple times can give different results. This makes it undefined behavior to have |
46 | /// uninitialized data in a variable even if that variable has an integer type, which otherwise can |
47 | /// hold any *fixed* bit pattern: |
48 | /// |
49 | /// ```rust,no_run |
50 | /// # #![allow(invalid_value)] |
51 | /// use std::mem::{self, MaybeUninit}; |
52 | /// |
53 | /// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ |
54 | /// // The equivalent code with `MaybeUninit<i32>`: |
55 | /// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ |
56 | /// ``` |
57 | /// On top of that, remember that most types have additional invariants beyond merely |
58 | /// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`] |
59 | /// is considered initialized (under the current implementation; this does not constitute |
60 | /// a stable guarantee) because the only requirement the compiler knows about it |
61 | /// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause |
62 | /// *immediate* undefined behavior, but will cause undefined behavior with most |
63 | /// safe operations (including dropping it). |
64 | /// |
65 | /// [`Vec<T>`]: ../../std/vec/struct.Vec.html |
66 | /// |
67 | /// # Examples |
68 | /// |
69 | /// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data. |
70 | /// It is a signal to the compiler indicating that the data here might *not* |
71 | /// be initialized: |
72 | /// |
73 | /// ```rust |
74 | /// use std::mem::MaybeUninit; |
75 | /// |
76 | /// // Create an explicitly uninitialized reference. The compiler knows that data inside |
77 | /// // a `MaybeUninit<T>` may be invalid, and hence this is not UB: |
78 | /// let mut x = MaybeUninit::<&i32>::uninit(); |
79 | /// // Set it to a valid value. |
80 | /// x.write(&0); |
81 | /// // Extract the initialized data -- this is only allowed *after* properly |
82 | /// // initializing `x`! |
83 | /// let x = unsafe { x.assume_init() }; |
84 | /// ``` |
85 | /// |
86 | /// The compiler then knows to not make any incorrect assumptions or optimizations on this code. |
87 | /// |
88 | /// You can think of `MaybeUninit<T>` as being a bit like `Option<T>` but without |
89 | /// any of the run-time tracking and without any of the safety checks. |
90 | /// |
91 | /// ## out-pointers |
92 | /// |
93 | /// You can use `MaybeUninit<T>` to implement "out-pointers": instead of returning data |
94 | /// from a function, pass it a pointer to some (uninitialized) memory to put the |
95 | /// result into. This can be useful when it is important for the caller to control |
96 | /// how the memory the result is stored in gets allocated, and you want to avoid |
97 | /// unnecessary moves. |
98 | /// |
99 | /// ``` |
100 | /// use std::mem::MaybeUninit; |
101 | /// |
102 | /// unsafe fn make_vec(out: *mut Vec<i32>) { |
103 | /// // `write` does not drop the old contents, which is important. |
104 | /// out.write(vec![1, 2, 3]); |
105 | /// } |
106 | /// |
107 | /// let mut v = MaybeUninit::uninit(); |
108 | /// unsafe { make_vec(v.as_mut_ptr()); } |
109 | /// // Now we know `v` is initialized! This also makes sure the vector gets |
110 | /// // properly dropped. |
111 | /// let v = unsafe { v.assume_init() }; |
112 | /// assert_eq!(&v, &[1, 2, 3]); |
113 | /// ``` |
114 | /// |
115 | /// ## Initializing an array element-by-element |
116 | /// |
117 | /// `MaybeUninit<T>` can be used to initialize a large array element-by-element: |
118 | /// |
119 | /// ``` |
120 | /// use std::mem::{self, MaybeUninit}; |
121 | /// |
122 | /// let data = { |
123 | /// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is |
124 | /// // safe because the type we are claiming to have initialized here is a |
125 | /// // bunch of `MaybeUninit`s, which do not require initialization. |
126 | /// let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe { |
127 | /// MaybeUninit::uninit().assume_init() |
128 | /// }; |
129 | /// |
130 | /// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, |
131 | /// // we have a memory leak, but there is no memory safety issue. |
132 | /// for elem in &mut data[..] { |
133 | /// elem.write(vec![42]); |
134 | /// } |
135 | /// |
136 | /// // Everything is initialized. Transmute the array to the |
137 | /// // initialized type. |
138 | /// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) } |
139 | /// }; |
140 | /// |
141 | /// assert_eq!(&data[0], &[42]); |
142 | /// ``` |
143 | /// |
144 | /// You can also work with partially initialized arrays, which could |
145 | /// be found in low-level datastructures. |
146 | /// |
147 | /// ``` |
148 | /// use std::mem::MaybeUninit; |
149 | /// |
150 | /// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is |
151 | /// // safe because the type we are claiming to have initialized here is a |
152 | /// // bunch of `MaybeUninit`s, which do not require initialization. |
153 | /// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() }; |
154 | /// // Count the number of elements we have assigned. |
155 | /// let mut data_len: usize = 0; |
156 | /// |
157 | /// for elem in &mut data[0..500] { |
158 | /// elem.write(String::from("hello" )); |
159 | /// data_len += 1; |
160 | /// } |
161 | /// |
162 | /// // For each item in the array, drop if we allocated it. |
163 | /// for elem in &mut data[0..data_len] { |
164 | /// unsafe { elem.assume_init_drop(); } |
165 | /// } |
166 | /// ``` |
167 | /// |
168 | /// ## Initializing a struct field-by-field |
169 | /// |
170 | /// You can use `MaybeUninit<T>`, and the [`std::ptr::addr_of_mut`] macro, to initialize structs field by field: |
171 | /// |
172 | /// ```rust |
173 | /// use std::mem::MaybeUninit; |
174 | /// use std::ptr::addr_of_mut; |
175 | /// |
176 | /// #[derive(Debug, PartialEq)] |
177 | /// pub struct Foo { |
178 | /// name: String, |
179 | /// list: Vec<u8>, |
180 | /// } |
181 | /// |
182 | /// let foo = { |
183 | /// let mut uninit: MaybeUninit<Foo> = MaybeUninit::uninit(); |
184 | /// let ptr = uninit.as_mut_ptr(); |
185 | /// |
186 | /// // Initializing the `name` field |
187 | /// // Using `write` instead of assignment via `=` to not call `drop` on the |
188 | /// // old, uninitialized value. |
189 | /// unsafe { addr_of_mut!((*ptr).name).write("Bob" .to_string()); } |
190 | /// |
191 | /// // Initializing the `list` field |
192 | /// // If there is a panic here, then the `String` in the `name` field leaks. |
193 | /// unsafe { addr_of_mut!((*ptr).list).write(vec![0, 1, 2]); } |
194 | /// |
195 | /// // All the fields are initialized, so we call `assume_init` to get an initialized Foo. |
196 | /// unsafe { uninit.assume_init() } |
197 | /// }; |
198 | /// |
199 | /// assert_eq!( |
200 | /// foo, |
201 | /// Foo { |
202 | /// name: "Bob" .to_string(), |
203 | /// list: vec![0, 1, 2] |
204 | /// } |
205 | /// ); |
206 | /// ``` |
207 | /// [`std::ptr::addr_of_mut`]: crate::ptr::addr_of_mut |
208 | /// [ub]: ../../reference/behavior-considered-undefined.html |
209 | /// |
210 | /// # Layout |
211 | /// |
212 | /// `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as `T`: |
213 | /// |
214 | /// ```rust |
215 | /// use std::mem::{MaybeUninit, size_of, align_of}; |
216 | /// assert_eq!(size_of::<MaybeUninit<u64>>(), size_of::<u64>()); |
217 | /// assert_eq!(align_of::<MaybeUninit<u64>>(), align_of::<u64>()); |
218 | /// ``` |
219 | /// |
220 | /// However remember that a type *containing* a `MaybeUninit<T>` is not necessarily the same |
221 | /// layout; Rust does not in general guarantee that the fields of a `Foo<T>` have the same order as |
222 | /// a `Foo<U>` even if `T` and `U` have the same size and alignment. Furthermore because any bit |
223 | /// value is valid for a `MaybeUninit<T>` the compiler can't apply non-zero/niche-filling |
224 | /// optimizations, potentially resulting in a larger size: |
225 | /// |
226 | /// ```rust |
227 | /// # use std::mem::{MaybeUninit, size_of}; |
228 | /// assert_eq!(size_of::<Option<bool>>(), 1); |
229 | /// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2); |
230 | /// ``` |
231 | /// |
232 | /// If `T` is FFI-safe, then so is `MaybeUninit<T>`. |
233 | /// |
234 | /// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size, |
235 | /// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option<T>` and |
236 | /// `Option<MaybeUninit<T>>` may still have different sizes, and types containing a field of type |
237 | /// `T` may be laid out (and sized) differently than if that field were `MaybeUninit<T>`. |
238 | /// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the |
239 | /// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact |
240 | /// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not |
241 | /// remain `#[repr(transparent)]`. That said, `MaybeUninit<T>` will *always* guarantee that it has |
242 | /// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that |
243 | /// guarantee may evolve. |
244 | #[stable (feature = "maybe_uninit" , since = "1.36.0" )] |
245 | // Lang item so we can wrap other types in it. This is useful for coroutines. |
246 | #[lang = "maybe_uninit" ] |
247 | #[derive (Copy)] |
248 | #[repr (transparent)] |
249 | pub union MaybeUninit<T> { |
250 | uninit: (), |
251 | value: ManuallyDrop<T>, |
252 | } |
253 | |
254 | #[stable (feature = "maybe_uninit" , since = "1.36.0" )] |
255 | impl<T: Copy> Clone for MaybeUninit<T> { |
256 | #[inline (always)] |
257 | fn clone(&self) -> Self { |
258 | // Not calling `T::clone()`, we cannot know if we are initialized enough for that. |
259 | *self |
260 | } |
261 | } |
262 | |
263 | #[stable (feature = "maybe_uninit_debug" , since = "1.41.0" )] |
264 | impl<T> fmt::Debug for MaybeUninit<T> { |
265 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
266 | f.pad(type_name::<Self>()) |
267 | } |
268 | } |
269 | |
270 | impl<T> MaybeUninit<T> { |
271 | /// Creates a new `MaybeUninit<T>` initialized with the given value. |
272 | /// It is safe to call [`assume_init`] on the return value of this function. |
273 | /// |
274 | /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. |
275 | /// It is your responsibility to make sure `T` gets dropped if it got initialized. |
276 | /// |
277 | /// # Example |
278 | /// |
279 | /// ``` |
280 | /// use std::mem::MaybeUninit; |
281 | /// |
282 | /// let v: MaybeUninit<Vec<u8>> = MaybeUninit::new(vec![42]); |
283 | /// ``` |
284 | /// |
285 | /// [`assume_init`]: MaybeUninit::assume_init |
286 | #[stable (feature = "maybe_uninit" , since = "1.36.0" )] |
287 | #[rustc_const_stable (feature = "const_maybe_uninit" , since = "1.36.0" )] |
288 | #[must_use = "use `forget` to avoid running Drop code" ] |
289 | #[inline (always)] |
290 | pub const fn new(val: T) -> MaybeUninit<T> { |
291 | MaybeUninit { value: ManuallyDrop::new(val) } |
292 | } |
293 | |
294 | /// Creates a new `MaybeUninit<T>` in an uninitialized state. |
295 | /// |
296 | /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. |
297 | /// It is your responsibility to make sure `T` gets dropped if it got initialized. |
298 | /// |
299 | /// See the [type-level documentation][MaybeUninit] for some examples. |
300 | /// |
301 | /// # Example |
302 | /// |
303 | /// ``` |
304 | /// use std::mem::MaybeUninit; |
305 | /// |
306 | /// let v: MaybeUninit<String> = MaybeUninit::uninit(); |
307 | /// ``` |
308 | #[stable (feature = "maybe_uninit" , since = "1.36.0" )] |
309 | #[rustc_const_stable (feature = "const_maybe_uninit" , since = "1.36.0" )] |
310 | #[must_use ] |
311 | #[inline (always)] |
312 | #[rustc_diagnostic_item = "maybe_uninit_uninit" ] |
313 | pub const fn uninit() -> MaybeUninit<T> { |
314 | MaybeUninit { uninit: () } |
315 | } |
316 | |
317 | /// Create a new array of `MaybeUninit<T>` items, in an uninitialized state. |
318 | /// |
319 | /// Note: in a future Rust version this method may become unnecessary |
320 | /// when Rust allows |
321 | /// [inline const expressions](https://github.com/rust-lang/rust/issues/76001). |
322 | /// The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`. |
323 | /// |
324 | /// # Examples |
325 | /// |
326 | /// ```no_run |
327 | /// #![feature(maybe_uninit_uninit_array, maybe_uninit_slice)] |
328 | /// |
329 | /// use std::mem::MaybeUninit; |
330 | /// |
331 | /// extern "C" { |
332 | /// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize; |
333 | /// } |
334 | /// |
335 | /// /// Returns a (possibly smaller) slice of data that was actually read |
336 | /// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] { |
337 | /// unsafe { |
338 | /// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len()); |
339 | /// MaybeUninit::slice_assume_init_ref(&buf[..len]) |
340 | /// } |
341 | /// } |
342 | /// |
343 | /// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array(); |
344 | /// let data = read(&mut buf); |
345 | /// ``` |
346 | #[unstable (feature = "maybe_uninit_uninit_array" , issue = "96097" )] |
347 | #[rustc_const_unstable (feature = "const_maybe_uninit_uninit_array" , issue = "96097" )] |
348 | #[must_use ] |
349 | #[inline (always)] |
350 | pub const fn uninit_array<const N: usize>() -> [Self; N] { |
351 | // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid. |
352 | unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() } |
353 | } |
354 | |
355 | /// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being |
356 | /// filled with `0` bytes. It depends on `T` whether that already makes for |
357 | /// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized, |
358 | /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not |
359 | /// be null. |
360 | /// |
361 | /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. |
362 | /// It is your responsibility to make sure `T` gets dropped if it got initialized. |
363 | /// |
364 | /// # Example |
365 | /// |
366 | /// Correct usage of this function: initializing a struct with zero, where all |
367 | /// fields of the struct can hold the bit-pattern 0 as a valid value. |
368 | /// |
369 | /// ```rust |
370 | /// use std::mem::MaybeUninit; |
371 | /// |
372 | /// let x = MaybeUninit::<(u8, bool)>::zeroed(); |
373 | /// let x = unsafe { x.assume_init() }; |
374 | /// assert_eq!(x, (0, false)); |
375 | /// ``` |
376 | /// |
377 | /// This can be used in const contexts, such as to indicate the end of static arrays for |
378 | /// plugin registration. |
379 | /// |
380 | /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()` |
381 | /// when `0` is not a valid bit-pattern for the type: |
382 | /// |
383 | /// ```rust,no_run |
384 | /// use std::mem::MaybeUninit; |
385 | /// |
386 | /// enum NotZero { One = 1, Two = 2 } |
387 | /// |
388 | /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); |
389 | /// let x = unsafe { x.assume_init() }; |
390 | /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. |
391 | /// // This is undefined behavior. ⚠️ |
392 | /// ``` |
393 | #[inline ] |
394 | #[must_use ] |
395 | #[rustc_diagnostic_item = "maybe_uninit_zeroed" ] |
396 | #[stable (feature = "maybe_uninit" , since = "1.36.0" )] |
397 | // These are OK to allow since we do not leak &mut to user-visible API |
398 | #[rustc_allow_const_fn_unstable (const_mut_refs)] |
399 | #[rustc_allow_const_fn_unstable (const_ptr_write)] |
400 | #[rustc_allow_const_fn_unstable (const_maybe_uninit_as_mut_ptr)] |
401 | #[rustc_const_stable (feature = "const_maybe_uninit_zeroed" , since = "1.75.0" )] |
402 | pub const fn zeroed() -> MaybeUninit<T> { |
403 | let mut u = MaybeUninit::<T>::uninit(); |
404 | // SAFETY: `u.as_mut_ptr()` points to allocated memory. |
405 | unsafe { u.as_mut_ptr().write_bytes(0u8, 1) }; |
406 | u |
407 | } |
408 | |
409 | /// Sets the value of the `MaybeUninit<T>`. |
410 | /// |
411 | /// This overwrites any previous value without dropping it, so be careful |
412 | /// not to use this twice unless you want to skip running the destructor. |
413 | /// For your convenience, this also returns a mutable reference to the |
414 | /// (now safely initialized) contents of `self`. |
415 | /// |
416 | /// As the content is stored inside a `MaybeUninit`, the destructor is not |
417 | /// run for the inner data if the MaybeUninit leaves scope without a call to |
418 | /// [`assume_init`], [`assume_init_drop`], or similar. Code that receives |
419 | /// the mutable reference returned by this function needs to keep this in |
420 | /// mind. The safety model of Rust regards leaks as safe, but they are |
421 | /// usually still undesirable. This being said, the mutable reference |
422 | /// behaves like any other mutable reference would, so assigning a new value |
423 | /// to it will drop the old content. |
424 | /// |
425 | /// [`assume_init`]: Self::assume_init |
426 | /// [`assume_init_drop`]: Self::assume_init_drop |
427 | /// |
428 | /// # Examples |
429 | /// |
430 | /// Correct usage of this method: |
431 | /// |
432 | /// ```rust |
433 | /// use std::mem::MaybeUninit; |
434 | /// |
435 | /// let mut x = MaybeUninit::<Vec<u8>>::uninit(); |
436 | /// |
437 | /// { |
438 | /// let hello = x.write((&b"Hello, world!" ).to_vec()); |
439 | /// // Setting hello does not leak prior allocations, but drops them |
440 | /// *hello = (&b"Hello" ).to_vec(); |
441 | /// hello[0] = 'h' as u8; |
442 | /// } |
443 | /// // x is initialized now: |
444 | /// let s = unsafe { x.assume_init() }; |
445 | /// assert_eq!(b"hello" , s.as_slice()); |
446 | /// ``` |
447 | /// |
448 | /// This usage of the method causes a leak: |
449 | /// |
450 | /// ```rust |
451 | /// use std::mem::MaybeUninit; |
452 | /// |
453 | /// let mut x = MaybeUninit::<String>::uninit(); |
454 | /// |
455 | /// x.write("Hello" .to_string()); |
456 | /// // This leaks the contained string: |
457 | /// x.write("hello" .to_string()); |
458 | /// // x is initialized now: |
459 | /// let s = unsafe { x.assume_init() }; |
460 | /// ``` |
461 | /// |
462 | /// This method can be used to avoid unsafe in some cases. The example below |
463 | /// shows a part of an implementation of a fixed sized arena that lends out |
464 | /// pinned references. |
465 | /// With `write`, we can avoid the need to write through a raw pointer: |
466 | /// |
467 | /// ```rust |
468 | /// use core::pin::Pin; |
469 | /// use core::mem::MaybeUninit; |
470 | /// |
471 | /// struct PinArena<T> { |
472 | /// memory: Box<[MaybeUninit<T>]>, |
473 | /// len: usize, |
474 | /// } |
475 | /// |
476 | /// impl <T> PinArena<T> { |
477 | /// pub fn capacity(&self) -> usize { |
478 | /// self.memory.len() |
479 | /// } |
480 | /// pub fn push(&mut self, val: T) -> Pin<&mut T> { |
481 | /// if self.len >= self.capacity() { |
482 | /// panic!("Attempted to push to a full pin arena!" ); |
483 | /// } |
484 | /// let ref_ = self.memory[self.len].write(val); |
485 | /// self.len += 1; |
486 | /// unsafe { Pin::new_unchecked(ref_) } |
487 | /// } |
488 | /// } |
489 | /// ``` |
490 | #[stable (feature = "maybe_uninit_write" , since = "1.55.0" )] |
491 | #[rustc_const_unstable (feature = "const_maybe_uninit_write" , issue = "63567" )] |
492 | #[inline (always)] |
493 | pub const fn write(&mut self, val: T) -> &mut T { |
494 | *self = MaybeUninit::new(val); |
495 | // SAFETY: We just initialized this value. |
496 | unsafe { self.assume_init_mut() } |
497 | } |
498 | |
499 | /// Gets a pointer to the contained value. Reading from this pointer or turning it |
500 | /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized. |
501 | /// Writing to memory that this pointer (non-transitively) points to is undefined behavior |
502 | /// (except inside an `UnsafeCell<T>`). |
503 | /// |
504 | /// # Examples |
505 | /// |
506 | /// Correct usage of this method: |
507 | /// |
508 | /// ```rust |
509 | /// use std::mem::MaybeUninit; |
510 | /// |
511 | /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); |
512 | /// x.write(vec![0, 1, 2]); |
513 | /// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it. |
514 | /// let x_vec = unsafe { &*x.as_ptr() }; |
515 | /// assert_eq!(x_vec.len(), 3); |
516 | /// ``` |
517 | /// |
518 | /// *Incorrect* usage of this method: |
519 | /// |
520 | /// ```rust,no_run |
521 | /// use std::mem::MaybeUninit; |
522 | /// |
523 | /// let x = MaybeUninit::<Vec<u32>>::uninit(); |
524 | /// let x_vec = unsafe { &*x.as_ptr() }; |
525 | /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ |
526 | /// ``` |
527 | /// |
528 | /// (Notice that the rules around references to uninitialized data are not finalized yet, but |
529 | /// until they are, it is advisable to avoid them.) |
530 | #[stable (feature = "maybe_uninit" , since = "1.36.0" )] |
531 | #[rustc_const_stable (feature = "const_maybe_uninit_as_ptr" , since = "1.59.0" )] |
532 | #[inline (always)] |
533 | pub const fn as_ptr(&self) -> *const T { |
534 | // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. |
535 | self as *const _ as *const T |
536 | } |
537 | |
538 | /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it |
539 | /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized. |
540 | /// |
541 | /// # Examples |
542 | /// |
543 | /// Correct usage of this method: |
544 | /// |
545 | /// ```rust |
546 | /// use std::mem::MaybeUninit; |
547 | /// |
548 | /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); |
549 | /// x.write(vec![0, 1, 2]); |
550 | /// // Create a reference into the `MaybeUninit<Vec<u32>>`. |
551 | /// // This is okay because we initialized it. |
552 | /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; |
553 | /// x_vec.push(3); |
554 | /// assert_eq!(x_vec.len(), 4); |
555 | /// ``` |
556 | /// |
557 | /// *Incorrect* usage of this method: |
558 | /// |
559 | /// ```rust,no_run |
560 | /// use std::mem::MaybeUninit; |
561 | /// |
562 | /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); |
563 | /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; |
564 | /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ |
565 | /// ``` |
566 | /// |
567 | /// (Notice that the rules around references to uninitialized data are not finalized yet, but |
568 | /// until they are, it is advisable to avoid them.) |
569 | #[stable (feature = "maybe_uninit" , since = "1.36.0" )] |
570 | #[rustc_const_unstable (feature = "const_maybe_uninit_as_mut_ptr" , issue = "75251" )] |
571 | #[inline (always)] |
572 | pub const fn as_mut_ptr(&mut self) -> *mut T { |
573 | // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. |
574 | self as *mut _ as *mut T |
575 | } |
576 | |
577 | /// Extracts the value from the `MaybeUninit<T>` container. This is a great way |
578 | /// to ensure that the data will get dropped, because the resulting `T` is |
579 | /// subject to the usual drop handling. |
580 | /// |
581 | /// # Safety |
582 | /// |
583 | /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized |
584 | /// state. Calling this when the content is not yet fully initialized causes immediate undefined |
585 | /// behavior. The [type-level documentation][inv] contains more information about |
586 | /// this initialization invariant. |
587 | /// |
588 | /// [inv]: #initialization-invariant |
589 | /// |
590 | /// On top of that, remember that most types have additional invariants beyond merely |
591 | /// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`] |
592 | /// is considered initialized (under the current implementation; this does not constitute |
593 | /// a stable guarantee) because the only requirement the compiler knows about it |
594 | /// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause |
595 | /// *immediate* undefined behavior, but will cause undefined behavior with most |
596 | /// safe operations (including dropping it). |
597 | /// |
598 | /// [`Vec<T>`]: ../../std/vec/struct.Vec.html |
599 | /// |
600 | /// # Examples |
601 | /// |
602 | /// Correct usage of this method: |
603 | /// |
604 | /// ```rust |
605 | /// use std::mem::MaybeUninit; |
606 | /// |
607 | /// let mut x = MaybeUninit::<bool>::uninit(); |
608 | /// x.write(true); |
609 | /// let x_init = unsafe { x.assume_init() }; |
610 | /// assert_eq!(x_init, true); |
611 | /// ``` |
612 | /// |
613 | /// *Incorrect* usage of this method: |
614 | /// |
615 | /// ```rust,no_run |
616 | /// use std::mem::MaybeUninit; |
617 | /// |
618 | /// let x = MaybeUninit::<Vec<u32>>::uninit(); |
619 | /// let x_init = unsafe { x.assume_init() }; |
620 | /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️ |
621 | /// ``` |
622 | #[stable (feature = "maybe_uninit" , since = "1.36.0" )] |
623 | #[rustc_const_stable (feature = "const_maybe_uninit_assume_init_by_value" , since = "1.59.0" )] |
624 | #[inline (always)] |
625 | #[rustc_diagnostic_item = "assume_init" ] |
626 | #[track_caller ] |
627 | pub const unsafe fn assume_init(self) -> T { |
628 | // SAFETY: the caller must guarantee that `self` is initialized. |
629 | // This also means that `self` must be a `value` variant. |
630 | unsafe { |
631 | intrinsics::assert_inhabited::<T>(); |
632 | ManuallyDrop::into_inner(self.value) |
633 | } |
634 | } |
635 | |
636 | /// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject |
637 | /// to the usual drop handling. |
638 | /// |
639 | /// Whenever possible, it is preferable to use [`assume_init`] instead, which |
640 | /// prevents duplicating the content of the `MaybeUninit<T>`. |
641 | /// |
642 | /// # Safety |
643 | /// |
644 | /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized |
645 | /// state. Calling this when the content is not yet fully initialized causes undefined |
646 | /// behavior. The [type-level documentation][inv] contains more information about |
647 | /// this initialization invariant. |
648 | /// |
649 | /// Moreover, similar to the [`ptr::read`] function, this function creates a |
650 | /// bitwise copy of the contents, regardless whether the contained type |
651 | /// implements the [`Copy`] trait or not. When using multiple copies of the |
652 | /// data (by calling `assume_init_read` multiple times, or first calling |
653 | /// `assume_init_read` and then [`assume_init`]), it is your responsibility |
654 | /// to ensure that data may indeed be duplicated. |
655 | /// |
656 | /// [inv]: #initialization-invariant |
657 | /// [`assume_init`]: MaybeUninit::assume_init |
658 | /// |
659 | /// # Examples |
660 | /// |
661 | /// Correct usage of this method: |
662 | /// |
663 | /// ```rust |
664 | /// use std::mem::MaybeUninit; |
665 | /// |
666 | /// let mut x = MaybeUninit::<u32>::uninit(); |
667 | /// x.write(13); |
668 | /// let x1 = unsafe { x.assume_init_read() }; |
669 | /// // `u32` is `Copy`, so we may read multiple times. |
670 | /// let x2 = unsafe { x.assume_init_read() }; |
671 | /// assert_eq!(x1, x2); |
672 | /// |
673 | /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit(); |
674 | /// x.write(None); |
675 | /// let x1 = unsafe { x.assume_init_read() }; |
676 | /// // Duplicating a `None` value is okay, so we may read multiple times. |
677 | /// let x2 = unsafe { x.assume_init_read() }; |
678 | /// assert_eq!(x1, x2); |
679 | /// ``` |
680 | /// |
681 | /// *Incorrect* usage of this method: |
682 | /// |
683 | /// ```rust,no_run |
684 | /// use std::mem::MaybeUninit; |
685 | /// |
686 | /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit(); |
687 | /// x.write(Some(vec![0, 1, 2])); |
688 | /// let x1 = unsafe { x.assume_init_read() }; |
689 | /// let x2 = unsafe { x.assume_init_read() }; |
690 | /// // We now created two copies of the same vector, leading to a double-free ⚠️ when |
691 | /// // they both get dropped! |
692 | /// ``` |
693 | #[stable (feature = "maybe_uninit_extra" , since = "1.60.0" )] |
694 | #[rustc_const_stable (feature = "const_maybe_uninit_assume_init_read" , since = "1.75.0" )] |
695 | #[inline (always)] |
696 | #[track_caller ] |
697 | pub const unsafe fn assume_init_read(&self) -> T { |
698 | // SAFETY: the caller must guarantee that `self` is initialized. |
699 | // Reading from `self.as_ptr()` is safe since `self` should be initialized. |
700 | unsafe { |
701 | intrinsics::assert_inhabited::<T>(); |
702 | self.as_ptr().read() |
703 | } |
704 | } |
705 | |
706 | /// Drops the contained value in place. |
707 | /// |
708 | /// If you have ownership of the `MaybeUninit`, you can also use |
709 | /// [`assume_init`] as an alternative. |
710 | /// |
711 | /// # Safety |
712 | /// |
713 | /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is |
714 | /// in an initialized state. Calling this when the content is not yet fully |
715 | /// initialized causes undefined behavior. |
716 | /// |
717 | /// On top of that, all additional invariants of the type `T` must be |
718 | /// satisfied, as the `Drop` implementation of `T` (or its members) may |
719 | /// rely on this. For example, setting a [`Vec<T>`] to an invalid but |
720 | /// non-null address makes it initialized (under the current implementation; |
721 | /// this does not constitute a stable guarantee), because the only |
722 | /// requirement the compiler knows about it is that the data pointer must be |
723 | /// non-null. Dropping such a `Vec<T>` however will cause undefined |
724 | /// behaviour. |
725 | /// |
726 | /// [`assume_init`]: MaybeUninit::assume_init |
727 | /// [`Vec<T>`]: ../../std/vec/struct.Vec.html |
728 | #[stable (feature = "maybe_uninit_extra" , since = "1.60.0" )] |
729 | pub unsafe fn assume_init_drop(&mut self) { |
730 | // SAFETY: the caller must guarantee that `self` is initialized and |
731 | // satisfies all invariants of `T`. |
732 | // Dropping the value in place is safe if that is the case. |
733 | unsafe { ptr::drop_in_place(self.as_mut_ptr()) } |
734 | } |
735 | |
736 | /// Gets a shared reference to the contained value. |
737 | /// |
738 | /// This can be useful when we want to access a `MaybeUninit` that has been |
739 | /// initialized but don't have ownership of the `MaybeUninit` (preventing the use |
740 | /// of `.assume_init()`). |
741 | /// |
742 | /// # Safety |
743 | /// |
744 | /// Calling this when the content is not yet fully initialized causes undefined |
745 | /// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really |
746 | /// is in an initialized state. |
747 | /// |
748 | /// # Examples |
749 | /// |
750 | /// ### Correct usage of this method: |
751 | /// |
752 | /// ```rust |
753 | /// use std::mem::MaybeUninit; |
754 | /// |
755 | /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); |
756 | /// // Initialize `x`: |
757 | /// x.write(vec![1, 2, 3]); |
758 | /// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to |
759 | /// // create a shared reference to it: |
760 | /// let x: &Vec<u32> = unsafe { |
761 | /// // SAFETY: `x` has been initialized. |
762 | /// x.assume_init_ref() |
763 | /// }; |
764 | /// assert_eq!(x, &vec![1, 2, 3]); |
765 | /// ``` |
766 | /// |
767 | /// ### *Incorrect* usages of this method: |
768 | /// |
769 | /// ```rust,no_run |
770 | /// use std::mem::MaybeUninit; |
771 | /// |
772 | /// let x = MaybeUninit::<Vec<u32>>::uninit(); |
773 | /// let x_vec: &Vec<u32> = unsafe { x.assume_init_ref() }; |
774 | /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ |
775 | /// ``` |
776 | /// |
777 | /// ```rust,no_run |
778 | /// use std::{cell::Cell, mem::MaybeUninit}; |
779 | /// |
780 | /// let b = MaybeUninit::<Cell<bool>>::uninit(); |
781 | /// // Initialize the `MaybeUninit` using `Cell::set`: |
782 | /// unsafe { |
783 | /// b.assume_init_ref().set(true); |
784 | /// // ^^^^^^^^^^^^^^^ |
785 | /// // Reference to an uninitialized `Cell<bool>`: UB! |
786 | /// } |
787 | /// ``` |
788 | #[stable (feature = "maybe_uninit_ref" , since = "1.55.0" )] |
789 | #[rustc_const_stable (feature = "const_maybe_uninit_assume_init_ref" , since = "1.59.0" )] |
790 | #[inline (always)] |
791 | pub const unsafe fn assume_init_ref(&self) -> &T { |
792 | // SAFETY: the caller must guarantee that `self` is initialized. |
793 | // This also means that `self` must be a `value` variant. |
794 | unsafe { |
795 | intrinsics::assert_inhabited::<T>(); |
796 | &*self.as_ptr() |
797 | } |
798 | } |
799 | |
800 | /// Gets a mutable (unique) reference to the contained value. |
801 | /// |
802 | /// This can be useful when we want to access a `MaybeUninit` that has been |
803 | /// initialized but don't have ownership of the `MaybeUninit` (preventing the use |
804 | /// of `.assume_init()`). |
805 | /// |
806 | /// # Safety |
807 | /// |
808 | /// Calling this when the content is not yet fully initialized causes undefined |
809 | /// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really |
810 | /// is in an initialized state. For instance, `.assume_init_mut()` cannot be used to |
811 | /// initialize a `MaybeUninit`. |
812 | /// |
813 | /// # Examples |
814 | /// |
815 | /// ### Correct usage of this method: |
816 | /// |
817 | /// ```rust |
818 | /// # #![allow (unexpected_cfgs)] |
819 | /// use std::mem::MaybeUninit; |
820 | /// |
821 | /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { *buf = [0; 1024] } |
822 | /// # #[cfg (FALSE)] |
823 | /// extern "C" { |
824 | /// /// Initializes *all* the bytes of the input buffer. |
825 | /// fn initialize_buffer(buf: *mut [u8; 1024]); |
826 | /// } |
827 | /// |
828 | /// let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); |
829 | /// |
830 | /// // Initialize `buf`: |
831 | /// unsafe { initialize_buffer(buf.as_mut_ptr()); } |
832 | /// // Now we know that `buf` has been initialized, so we could `.assume_init()` it. |
833 | /// // However, using `.assume_init()` may trigger a `memcpy` of the 1024 bytes. |
834 | /// // To assert our buffer has been initialized without copying it, we upgrade |
835 | /// // the `&mut MaybeUninit<[u8; 1024]>` to a `&mut [u8; 1024]`: |
836 | /// let buf: &mut [u8; 1024] = unsafe { |
837 | /// // SAFETY: `buf` has been initialized. |
838 | /// buf.assume_init_mut() |
839 | /// }; |
840 | /// |
841 | /// // Now we can use `buf` as a normal slice: |
842 | /// buf.sort_unstable(); |
843 | /// assert!( |
844 | /// buf.windows(2).all(|pair| pair[0] <= pair[1]), |
845 | /// "buffer is sorted" , |
846 | /// ); |
847 | /// ``` |
848 | /// |
849 | /// ### *Incorrect* usages of this method: |
850 | /// |
851 | /// You cannot use `.assume_init_mut()` to initialize a value: |
852 | /// |
853 | /// ```rust,no_run |
854 | /// use std::mem::MaybeUninit; |
855 | /// |
856 | /// let mut b = MaybeUninit::<bool>::uninit(); |
857 | /// unsafe { |
858 | /// *b.assume_init_mut() = true; |
859 | /// // We have created a (mutable) reference to an uninitialized `bool`! |
860 | /// // This is undefined behavior. ⚠️ |
861 | /// } |
862 | /// ``` |
863 | /// |
864 | /// For instance, you cannot [`Read`] into an uninitialized buffer: |
865 | /// |
866 | /// [`Read`]: ../../std/io/trait.Read.html |
867 | /// |
868 | /// ```rust,no_run |
869 | /// use std::{io, mem::MaybeUninit}; |
870 | /// |
871 | /// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]> |
872 | /// { |
873 | /// let mut buffer = MaybeUninit::<[u8; 64]>::uninit(); |
874 | /// reader.read_exact(unsafe { buffer.assume_init_mut() })?; |
875 | /// // ^^^^^^^^^^^^^^^^^^^^^^^^ |
876 | /// // (mutable) reference to uninitialized memory! |
877 | /// // This is undefined behavior. |
878 | /// Ok(unsafe { buffer.assume_init() }) |
879 | /// } |
880 | /// ``` |
881 | /// |
882 | /// Nor can you use direct field access to do field-by-field gradual initialization: |
883 | /// |
884 | /// ```rust,no_run |
885 | /// use std::{mem::MaybeUninit, ptr}; |
886 | /// |
887 | /// struct Foo { |
888 | /// a: u32, |
889 | /// b: u8, |
890 | /// } |
891 | /// |
892 | /// let foo: Foo = unsafe { |
893 | /// let mut foo = MaybeUninit::<Foo>::uninit(); |
894 | /// ptr::write(&mut foo.assume_init_mut().a as *mut u32, 1337); |
895 | /// // ^^^^^^^^^^^^^^^^^^^^^ |
896 | /// // (mutable) reference to uninitialized memory! |
897 | /// // This is undefined behavior. |
898 | /// ptr::write(&mut foo.assume_init_mut().b as *mut u8, 42); |
899 | /// // ^^^^^^^^^^^^^^^^^^^^^ |
900 | /// // (mutable) reference to uninitialized memory! |
901 | /// // This is undefined behavior. |
902 | /// foo.assume_init() |
903 | /// }; |
904 | /// ``` |
905 | #[stable (feature = "maybe_uninit_ref" , since = "1.55.0" )] |
906 | #[rustc_const_unstable (feature = "const_maybe_uninit_assume_init" , issue = "none" )] |
907 | #[inline (always)] |
908 | pub const unsafe fn assume_init_mut(&mut self) -> &mut T { |
909 | // SAFETY: the caller must guarantee that `self` is initialized. |
910 | // This also means that `self` must be a `value` variant. |
911 | unsafe { |
912 | intrinsics::assert_inhabited::<T>(); |
913 | &mut *self.as_mut_ptr() |
914 | } |
915 | } |
916 | |
917 | /// Extracts the values from an array of `MaybeUninit` containers. |
918 | /// |
919 | /// # Safety |
920 | /// |
921 | /// It is up to the caller to guarantee that all elements of the array are |
922 | /// in an initialized state. |
923 | /// |
924 | /// # Examples |
925 | /// |
926 | /// ``` |
927 | /// #![feature(maybe_uninit_uninit_array)] |
928 | /// #![feature(maybe_uninit_array_assume_init)] |
929 | /// use std::mem::MaybeUninit; |
930 | /// |
931 | /// let mut array: [MaybeUninit<i32>; 3] = MaybeUninit::uninit_array(); |
932 | /// array[0].write(0); |
933 | /// array[1].write(1); |
934 | /// array[2].write(2); |
935 | /// |
936 | /// // SAFETY: Now safe as we initialised all elements |
937 | /// let array = unsafe { |
938 | /// MaybeUninit::array_assume_init(array) |
939 | /// }; |
940 | /// |
941 | /// assert_eq!(array, [0, 1, 2]); |
942 | /// ``` |
943 | #[unstable (feature = "maybe_uninit_array_assume_init" , issue = "96097" )] |
944 | #[rustc_const_unstable (feature = "const_maybe_uninit_array_assume_init" , issue = "96097" )] |
945 | #[inline (always)] |
946 | #[track_caller ] |
947 | pub const unsafe fn array_assume_init<const N: usize>(array: [Self; N]) -> [T; N] { |
948 | // SAFETY: |
949 | // * The caller guarantees that all elements of the array are initialized |
950 | // * `MaybeUninit<T>` and T are guaranteed to have the same layout |
951 | // * `MaybeUninit` does not drop, so there are no double-frees |
952 | // And thus the conversion is safe |
953 | unsafe { |
954 | intrinsics::assert_inhabited::<[T; N]>(); |
955 | intrinsics::transmute_unchecked(array) |
956 | } |
957 | } |
958 | |
959 | /// Assuming all the elements are initialized, get a slice to them. |
960 | /// |
961 | /// # Safety |
962 | /// |
963 | /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements |
964 | /// really are in an initialized state. |
965 | /// Calling this when the content is not yet fully initialized causes undefined behavior. |
966 | /// |
967 | /// See [`assume_init_ref`] for more details and examples. |
968 | /// |
969 | /// [`assume_init_ref`]: MaybeUninit::assume_init_ref |
970 | #[unstable (feature = "maybe_uninit_slice" , issue = "63569" )] |
971 | #[rustc_const_unstable (feature = "maybe_uninit_slice" , issue = "63569" )] |
972 | #[inline (always)] |
973 | pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] { |
974 | // SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that |
975 | // `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`. |
976 | // The pointer obtained is valid since it refers to memory owned by `slice` which is a |
977 | // reference and thus guaranteed to be valid for reads. |
978 | unsafe { &*(slice as *const [Self] as *const [T]) } |
979 | } |
980 | |
981 | /// Assuming all the elements are initialized, get a mutable slice to them. |
982 | /// |
983 | /// # Safety |
984 | /// |
985 | /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements |
986 | /// really are in an initialized state. |
987 | /// Calling this when the content is not yet fully initialized causes undefined behavior. |
988 | /// |
989 | /// See [`assume_init_mut`] for more details and examples. |
990 | /// |
991 | /// [`assume_init_mut`]: MaybeUninit::assume_init_mut |
992 | #[unstable (feature = "maybe_uninit_slice" , issue = "63569" )] |
993 | #[rustc_const_unstable (feature = "const_maybe_uninit_assume_init" , issue = "none" )] |
994 | #[inline (always)] |
995 | pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] { |
996 | // SAFETY: similar to safety notes for `slice_get_ref`, but we have a |
997 | // mutable reference which is also guaranteed to be valid for writes. |
998 | unsafe { &mut *(slice as *mut [Self] as *mut [T]) } |
999 | } |
1000 | |
1001 | /// Gets a pointer to the first element of the array. |
1002 | #[unstable (feature = "maybe_uninit_slice" , issue = "63569" )] |
1003 | #[rustc_const_unstable (feature = "maybe_uninit_slice" , issue = "63569" )] |
1004 | #[inline (always)] |
1005 | pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T { |
1006 | this.as_ptr() as *const T |
1007 | } |
1008 | |
1009 | /// Gets a mutable pointer to the first element of the array. |
1010 | #[unstable (feature = "maybe_uninit_slice" , issue = "63569" )] |
1011 | #[rustc_const_unstable (feature = "maybe_uninit_slice" , issue = "63569" )] |
1012 | #[inline (always)] |
1013 | pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T { |
1014 | this.as_mut_ptr() as *mut T |
1015 | } |
1016 | |
1017 | /// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`. |
1018 | /// |
1019 | /// If `T` does not implement `Copy`, use [`write_slice_cloned`] |
1020 | /// |
1021 | /// This is similar to [`slice::copy_from_slice`]. |
1022 | /// |
1023 | /// # Panics |
1024 | /// |
1025 | /// This function will panic if the two slices have different lengths. |
1026 | /// |
1027 | /// # Examples |
1028 | /// |
1029 | /// ``` |
1030 | /// #![feature(maybe_uninit_write_slice)] |
1031 | /// use std::mem::MaybeUninit; |
1032 | /// |
1033 | /// let mut dst = [MaybeUninit::uninit(); 32]; |
1034 | /// let src = [0; 32]; |
1035 | /// |
1036 | /// let init = MaybeUninit::write_slice(&mut dst, &src); |
1037 | /// |
1038 | /// assert_eq!(init, src); |
1039 | /// ``` |
1040 | /// |
1041 | /// ``` |
1042 | /// #![feature(maybe_uninit_write_slice)] |
1043 | /// use std::mem::MaybeUninit; |
1044 | /// |
1045 | /// let mut vec = Vec::with_capacity(32); |
1046 | /// let src = [0; 16]; |
1047 | /// |
1048 | /// MaybeUninit::write_slice(&mut vec.spare_capacity_mut()[..src.len()], &src); |
1049 | /// |
1050 | /// // SAFETY: we have just copied all the elements of len into the spare capacity |
1051 | /// // the first src.len() elements of the vec are valid now. |
1052 | /// unsafe { |
1053 | /// vec.set_len(src.len()); |
1054 | /// } |
1055 | /// |
1056 | /// assert_eq!(vec, src); |
1057 | /// ``` |
1058 | /// |
1059 | /// [`write_slice_cloned`]: MaybeUninit::write_slice_cloned |
1060 | #[unstable (feature = "maybe_uninit_write_slice" , issue = "79995" )] |
1061 | pub fn write_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T] |
1062 | where |
1063 | T: Copy, |
1064 | { |
1065 | // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout |
1066 | let uninit_src: &[MaybeUninit<T>] = unsafe { super::transmute(src) }; |
1067 | |
1068 | this.copy_from_slice(uninit_src); |
1069 | |
1070 | // SAFETY: Valid elements have just been copied into `this` so it is initialized |
1071 | unsafe { MaybeUninit::slice_assume_init_mut(this) } |
1072 | } |
1073 | |
1074 | /// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`. |
1075 | /// Any already initialized elements will not be dropped. |
1076 | /// |
1077 | /// If `T` implements `Copy`, use [`write_slice`] |
1078 | /// |
1079 | /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements. |
1080 | /// |
1081 | /// # Panics |
1082 | /// |
1083 | /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics. |
1084 | /// |
1085 | /// If there is a panic, the already cloned elements will be dropped. |
1086 | /// |
1087 | /// # Examples |
1088 | /// |
1089 | /// ``` |
1090 | /// #![feature(maybe_uninit_write_slice)] |
1091 | /// use std::mem::MaybeUninit; |
1092 | /// |
1093 | /// let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; |
1094 | /// let src = ["wibbly" .to_string(), "wobbly" .to_string(), "timey" .to_string(), "wimey" .to_string(), "stuff" .to_string()]; |
1095 | /// |
1096 | /// let init = MaybeUninit::write_slice_cloned(&mut dst, &src); |
1097 | /// |
1098 | /// assert_eq!(init, src); |
1099 | /// ``` |
1100 | /// |
1101 | /// ``` |
1102 | /// #![feature(maybe_uninit_write_slice)] |
1103 | /// use std::mem::MaybeUninit; |
1104 | /// |
1105 | /// let mut vec = Vec::with_capacity(32); |
1106 | /// let src = ["rust" , "is" , "a" , "pretty" , "cool" , "language" ]; |
1107 | /// |
1108 | /// MaybeUninit::write_slice_cloned(&mut vec.spare_capacity_mut()[..src.len()], &src); |
1109 | /// |
1110 | /// // SAFETY: we have just cloned all the elements of len into the spare capacity |
1111 | /// // the first src.len() elements of the vec are valid now. |
1112 | /// unsafe { |
1113 | /// vec.set_len(src.len()); |
1114 | /// } |
1115 | /// |
1116 | /// assert_eq!(vec, src); |
1117 | /// ``` |
1118 | /// |
1119 | /// [`write_slice`]: MaybeUninit::write_slice |
1120 | #[unstable (feature = "maybe_uninit_write_slice" , issue = "79995" )] |
1121 | pub fn write_slice_cloned<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T] |
1122 | where |
1123 | T: Clone, |
1124 | { |
1125 | // unlike copy_from_slice this does not call clone_from_slice on the slice |
1126 | // this is because `MaybeUninit<T: Clone>` does not implement Clone. |
1127 | |
1128 | struct Guard<'a, T> { |
1129 | slice: &'a mut [MaybeUninit<T>], |
1130 | initialized: usize, |
1131 | } |
1132 | |
1133 | impl<'a, T> Drop for Guard<'a, T> { |
1134 | fn drop(&mut self) { |
1135 | let initialized_part = &mut self.slice[..self.initialized]; |
1136 | // SAFETY: this raw slice will contain only initialized objects |
1137 | // that's why, it is allowed to drop it. |
1138 | unsafe { |
1139 | crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part)); |
1140 | } |
1141 | } |
1142 | } |
1143 | |
1144 | assert_eq!(this.len(), src.len(), "destination and source slices have different lengths" ); |
1145 | // NOTE: We need to explicitly slice them to the same length |
1146 | // for bounds checking to be elided, and the optimizer will |
1147 | // generate memcpy for simple cases (for example T = u8). |
1148 | let len = this.len(); |
1149 | let src = &src[..len]; |
1150 | |
1151 | // guard is needed b/c panic might happen during a clone |
1152 | let mut guard = Guard { slice: this, initialized: 0 }; |
1153 | |
1154 | for i in 0..len { |
1155 | guard.slice[i].write(src[i].clone()); |
1156 | guard.initialized += 1; |
1157 | } |
1158 | |
1159 | super::forget(guard); |
1160 | |
1161 | // SAFETY: Valid elements have just been written into `this` so it is initialized |
1162 | unsafe { MaybeUninit::slice_assume_init_mut(this) } |
1163 | } |
1164 | |
1165 | /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. |
1166 | /// |
1167 | /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still |
1168 | /// contain padding bytes which are left uninitialized. |
1169 | /// |
1170 | /// # Examples |
1171 | /// |
1172 | /// ``` |
1173 | /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)] |
1174 | /// use std::mem::MaybeUninit; |
1175 | /// |
1176 | /// let val = 0x12345678_i32; |
1177 | /// let uninit = MaybeUninit::new(val); |
1178 | /// let uninit_bytes = uninit.as_bytes(); |
1179 | /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(uninit_bytes) }; |
1180 | /// assert_eq!(bytes, val.to_ne_bytes()); |
1181 | /// ``` |
1182 | #[unstable (feature = "maybe_uninit_as_bytes" , issue = "93092" )] |
1183 | pub fn as_bytes(&self) -> &[MaybeUninit<u8>] { |
1184 | // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes |
1185 | unsafe { |
1186 | slice::from_raw_parts(self.as_ptr() as *const MaybeUninit<u8>, mem::size_of::<T>()) |
1187 | } |
1188 | } |
1189 | |
1190 | /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized |
1191 | /// bytes. |
1192 | /// |
1193 | /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still |
1194 | /// contain padding bytes which are left uninitialized. |
1195 | /// |
1196 | /// # Examples |
1197 | /// |
1198 | /// ``` |
1199 | /// #![feature(maybe_uninit_as_bytes)] |
1200 | /// use std::mem::MaybeUninit; |
1201 | /// |
1202 | /// let val = 0x12345678_i32; |
1203 | /// let mut uninit = MaybeUninit::new(val); |
1204 | /// let uninit_bytes = uninit.as_bytes_mut(); |
1205 | /// if cfg!(target_endian = "little" ) { |
1206 | /// uninit_bytes[0].write(0xcd); |
1207 | /// } else { |
1208 | /// uninit_bytes[3].write(0xcd); |
1209 | /// } |
1210 | /// let val2 = unsafe { uninit.assume_init() }; |
1211 | /// assert_eq!(val2, 0x123456cd); |
1212 | /// ``` |
1213 | #[unstable (feature = "maybe_uninit_as_bytes" , issue = "93092" )] |
1214 | pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] { |
1215 | // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes |
1216 | unsafe { |
1217 | slice::from_raw_parts_mut( |
1218 | self.as_mut_ptr() as *mut MaybeUninit<u8>, |
1219 | mem::size_of::<T>(), |
1220 | ) |
1221 | } |
1222 | } |
1223 | |
1224 | /// Returns the contents of this slice of `MaybeUninit` as a slice of potentially uninitialized |
1225 | /// bytes. |
1226 | /// |
1227 | /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still |
1228 | /// contain padding bytes which are left uninitialized. |
1229 | /// |
1230 | /// # Examples |
1231 | /// |
1232 | /// ``` |
1233 | /// #![feature(maybe_uninit_as_bytes, maybe_uninit_write_slice, maybe_uninit_slice)] |
1234 | /// use std::mem::MaybeUninit; |
1235 | /// |
1236 | /// let uninit = [MaybeUninit::new(0x1234u16), MaybeUninit::new(0x5678u16)]; |
1237 | /// let uninit_bytes = MaybeUninit::slice_as_bytes(&uninit); |
1238 | /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(&uninit_bytes) }; |
1239 | /// let val1 = u16::from_ne_bytes(bytes[0..2].try_into().unwrap()); |
1240 | /// let val2 = u16::from_ne_bytes(bytes[2..4].try_into().unwrap()); |
1241 | /// assert_eq!(&[val1, val2], &[0x1234u16, 0x5678u16]); |
1242 | /// ``` |
1243 | #[unstable (feature = "maybe_uninit_as_bytes" , issue = "93092" )] |
1244 | pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] { |
1245 | let bytes = mem::size_of_val(this); |
1246 | // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes |
1247 | unsafe { slice::from_raw_parts(this.as_ptr() as *const MaybeUninit<u8>, bytes) } |
1248 | } |
1249 | |
1250 | /// Returns the contents of this mutable slice of `MaybeUninit` as a mutable slice of |
1251 | /// potentially uninitialized bytes. |
1252 | /// |
1253 | /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still |
1254 | /// contain padding bytes which are left uninitialized. |
1255 | /// |
1256 | /// # Examples |
1257 | /// |
1258 | /// ``` |
1259 | /// #![feature(maybe_uninit_as_bytes, maybe_uninit_write_slice, maybe_uninit_slice)] |
1260 | /// use std::mem::MaybeUninit; |
1261 | /// |
1262 | /// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()]; |
1263 | /// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit); |
1264 | /// MaybeUninit::write_slice(uninit_bytes, &[0x12, 0x34, 0x56, 0x78]); |
1265 | /// let vals = unsafe { MaybeUninit::slice_assume_init_ref(&uninit) }; |
1266 | /// if cfg!(target_endian = "little" ) { |
1267 | /// assert_eq!(vals, &[0x3412u16, 0x7856u16]); |
1268 | /// } else { |
1269 | /// assert_eq!(vals, &[0x1234u16, 0x5678u16]); |
1270 | /// } |
1271 | /// ``` |
1272 | #[unstable (feature = "maybe_uninit_as_bytes" , issue = "93092" )] |
1273 | pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] { |
1274 | let bytes = mem::size_of_val(this); |
1275 | // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes |
1276 | unsafe { slice::from_raw_parts_mut(this.as_mut_ptr() as *mut MaybeUninit<u8>, bytes) } |
1277 | } |
1278 | } |
1279 | |
1280 | impl<T, const N: usize> MaybeUninit<[T; N]> { |
1281 | /// Transposes a `MaybeUninit<[T; N]>` into a `[MaybeUninit<T>; N]`. |
1282 | /// |
1283 | /// # Examples |
1284 | /// |
1285 | /// ``` |
1286 | /// #![feature(maybe_uninit_uninit_array_transpose)] |
1287 | /// # use std::mem::MaybeUninit; |
1288 | /// |
1289 | /// let data: [MaybeUninit<u8>; 1000] = MaybeUninit::uninit().transpose(); |
1290 | /// ``` |
1291 | #[unstable (feature = "maybe_uninit_uninit_array_transpose" , issue = "96097" )] |
1292 | #[inline ] |
1293 | pub const fn transpose(self) -> [MaybeUninit<T>; N] { |
1294 | // SAFETY: T and MaybeUninit<T> have the same layout |
1295 | unsafe { intrinsics::transmute_unchecked(self) } |
1296 | } |
1297 | } |
1298 | |
1299 | impl<T, const N: usize> [MaybeUninit<T>; N] { |
1300 | /// Transposes a `[MaybeUninit<T>; N]` into a `MaybeUninit<[T; N]>`. |
1301 | /// |
1302 | /// # Examples |
1303 | /// |
1304 | /// ``` |
1305 | /// #![feature(maybe_uninit_uninit_array_transpose)] |
1306 | /// # use std::mem::MaybeUninit; |
1307 | /// |
1308 | /// let data = [MaybeUninit::<u8>::uninit(); 1000]; |
1309 | /// let data: MaybeUninit<[u8; 1000]> = data.transpose(); |
1310 | /// ``` |
1311 | #[unstable (feature = "maybe_uninit_uninit_array_transpose" , issue = "96097" )] |
1312 | #[inline ] |
1313 | pub const fn transpose(self) -> MaybeUninit<[T; N]> { |
1314 | // SAFETY: T and MaybeUninit<T> have the same layout |
1315 | unsafe { intrinsics::transmute_unchecked(self) } |
1316 | } |
1317 | } |
1318 | |