1 use crate::any::type_name; 2 use crate::fmt; 3 use crate::intrinsics; 4 use crate::mem::ManuallyDrop; 5 use crate::ptr; 6 7 /// A wrapper type to construct uninitialized instances of `T`. 8 /// 9 /// # Initialization invariant 10 /// 11 /// The compiler, in general, assumes that a variable is properly initialized 12 /// according to the requirements of the variable's type. For example, a variable of 13 /// reference type must be aligned and non-null. This is an invariant that must 14 /// *always* be upheld, even in unsafe code. As a consequence, zero-initializing a 15 /// variable of reference type causes instantaneous [undefined behavior][ub], 16 /// no matter whether that reference ever gets used to access memory: 17 /// 18 /// ```rust,no_run 19 /// # #![allow(invalid_value)] 20 /// use std::mem::{self, MaybeUninit}; 21 /// 22 /// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! ⚠️ 23 /// // The equivalent code with `MaybeUninit<&i32>`: 24 /// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! ⚠️ 25 /// ``` 26 /// 27 /// This is exploited by the compiler for various optimizations, such as eliding 28 /// run-time checks and optimizing `enum` layout. 29 /// 30 /// Similarly, entirely uninitialized memory may have any content, while a `bool` must 31 /// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: 32 /// 33 /// ```rust,no_run 34 /// # #![allow(invalid_value)] 35 /// use std::mem::{self, MaybeUninit}; 36 /// 37 /// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ 38 /// // The equivalent code with `MaybeUninit<bool>`: 39 /// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ 40 /// ``` 41 /// 42 /// Moreover, uninitialized memory is special in that it does not have a fixed value ("fixed" 43 /// meaning "it won't change without being written to"). Reading the same uninitialized byte 44 /// multiple times can give different results. This makes it undefined behavior to have 45 /// uninitialized data in a variable even if that variable has an integer type, which otherwise can 46 /// hold any *fixed* bit pattern: 47 /// 48 /// ```rust,no_run 49 /// # #![allow(invalid_value)] 50 /// use std::mem::{self, MaybeUninit}; 51 /// 52 /// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ 53 /// // The equivalent code with `MaybeUninit<i32>`: 54 /// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ 55 /// ``` 56 /// (Notice that the rules around uninitialized integers are not finalized yet, but 57 /// until they are, it is advisable to avoid them.) 58 /// 59 /// On top of that, remember that most types have additional invariants beyond merely 60 /// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`] 61 /// is considered initialized (under the current implementation; this does not constitute 62 /// a stable guarantee) because the only requirement the compiler knows about it 63 /// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause 64 /// *immediate* undefined behavior, but will cause undefined behavior with most 65 /// safe operations (including dropping it). 66 /// 67 /// [`Vec<T>`]: ../../std/vec/struct.Vec.html 68 /// 69 /// # Examples 70 /// 71 /// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data. 72 /// It is a signal to the compiler indicating that the data here might *not* 73 /// be initialized: 74 /// 75 /// ```rust 76 /// use std::mem::MaybeUninit; 77 /// 78 /// // Create an explicitly uninitialized reference. The compiler knows that data inside 79 /// // a `MaybeUninit<T>` may be invalid, and hence this is not UB: 80 /// let mut x = MaybeUninit::<&i32>::uninit(); 81 /// // Set it to a valid value. 82 /// x.write(&0); 83 /// // Extract the initialized data -- this is only allowed *after* properly 84 /// // initializing `x`! 85 /// let x = unsafe { x.assume_init() }; 86 /// ``` 87 /// 88 /// The compiler then knows to not make any incorrect assumptions or optimizations on this code. 89 /// 90 /// You can think of `MaybeUninit<T>` as being a bit like `Option<T>` but without 91 /// any of the run-time tracking and without any of the safety checks. 92 /// 93 /// ## out-pointers 94 /// 95 /// You can use `MaybeUninit<T>` to implement "out-pointers": instead of returning data 96 /// from a function, pass it a pointer to some (uninitialized) memory to put the 97 /// result into. This can be useful when it is important for the caller to control 98 /// how the memory the result is stored in gets allocated, and you want to avoid 99 /// unnecessary moves. 100 /// 101 /// ``` 102 /// use std::mem::MaybeUninit; 103 /// 104 /// unsafe fn make_vec(out: *mut Vec<i32>) { 105 /// // `write` does not drop the old contents, which is important. 106 /// out.write(vec![1, 2, 3]); 107 /// } 108 /// 109 /// let mut v = MaybeUninit::uninit(); 110 /// unsafe { make_vec(v.as_mut_ptr()); } 111 /// // Now we know `v` is initialized! This also makes sure the vector gets 112 /// // properly dropped. 113 /// let v = unsafe { v.assume_init() }; 114 /// assert_eq!(&v, &[1, 2, 3]); 115 /// ``` 116 /// 117 /// ## Initializing an array element-by-element 118 /// 119 /// `MaybeUninit<T>` can be used to initialize a large array element-by-element: 120 /// 121 /// ``` 122 /// use std::mem::{self, MaybeUninit}; 123 /// 124 /// let data = { 125 /// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is 126 /// // safe because the type we are claiming to have initialized here is a 127 /// // bunch of `MaybeUninit`s, which do not require initialization. 128 /// let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe { 129 /// MaybeUninit::uninit().assume_init() 130 /// }; 131 /// 132 /// // Dropping a `MaybeUninit` does nothing. Thus using raw pointer 133 /// // assignment instead of `ptr::write` does not cause the old 134 /// // uninitialized value to be dropped. Also if there is a panic during 135 /// // this loop, we have a memory leak, but there is no memory safety 136 /// // issue. 137 /// for elem in &mut data[..] { 138 /// elem.write(vec![42]); 139 /// } 140 /// 141 /// // Everything is initialized. Transmute the array to the 142 /// // initialized type. 143 /// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) } 144 /// }; 145 /// 146 /// assert_eq!(&data[0], &[42]); 147 /// ``` 148 /// 149 /// You can also work with partially initialized arrays, which could 150 /// be found in low-level datastructures. 151 /// 152 /// ``` 153 /// use std::mem::MaybeUninit; 154 /// use std::ptr; 155 /// 156 /// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is 157 /// // safe because the type we are claiming to have initialized here is a 158 /// // bunch of `MaybeUninit`s, which do not require initialization. 159 /// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() }; 160 /// // Count the number of elements we have assigned. 161 /// let mut data_len: usize = 0; 162 /// 163 /// for elem in &mut data[0..500] { 164 /// elem.write(String::from("hello")); 165 /// data_len += 1; 166 /// } 167 /// 168 /// // For each item in the array, drop if we allocated it. 169 /// for elem in &mut data[0..data_len] { 170 /// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); } 171 /// } 172 /// ``` 173 /// 174 /// ## Initializing a struct field-by-field 175 /// 176 /// You can use `MaybeUninit<T>`, and the [`std::ptr::addr_of_mut`] macro, to initialize structs field by field: 177 /// 178 /// ```rust 179 /// use std::mem::MaybeUninit; 180 /// use std::ptr::addr_of_mut; 181 /// 182 /// #[derive(Debug, PartialEq)] 183 /// pub struct Foo { 184 /// name: String, 185 /// list: Vec<u8>, 186 /// } 187 /// 188 /// let foo = { 189 /// let mut uninit: MaybeUninit<Foo> = MaybeUninit::uninit(); 190 /// let ptr = uninit.as_mut_ptr(); 191 /// 192 /// // Initializing the `name` field 193 /// // Using `write` instead of assignment via `=` to not call `drop` on the 194 /// // old, uninitialized value. 195 /// unsafe { addr_of_mut!((*ptr).name).write("Bob".to_string()); } 196 /// 197 /// // Initializing the `list` field 198 /// // If there is a panic here, then the `String` in the `name` field leaks. 199 /// unsafe { addr_of_mut!((*ptr).list).write(vec![0, 1, 2]); } 200 /// 201 /// // All the fields are initialized, so we call `assume_init` to get an initialized Foo. 202 /// unsafe { uninit.assume_init() } 203 /// }; 204 /// 205 /// assert_eq!( 206 /// foo, 207 /// Foo { 208 /// name: "Bob".to_string(), 209 /// list: vec![0, 1, 2] 210 /// } 211 /// ); 212 /// ``` 213 /// [`std::ptr::addr_of_mut`]: crate::ptr::addr_of_mut 214 /// [ub]: ../../reference/behavior-considered-undefined.html 215 /// 216 /// # Layout 217 /// 218 /// `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as `T`: 219 /// 220 /// ```rust 221 /// use std::mem::{MaybeUninit, size_of, align_of}; 222 /// assert_eq!(size_of::<MaybeUninit<u64>>(), size_of::<u64>()); 223 /// assert_eq!(align_of::<MaybeUninit<u64>>(), align_of::<u64>()); 224 /// ``` 225 /// 226 /// However remember that a type *containing* a `MaybeUninit<T>` is not necessarily the same 227 /// layout; Rust does not in general guarantee that the fields of a `Foo<T>` have the same order as 228 /// a `Foo<U>` even if `T` and `U` have the same size and alignment. Furthermore because any bit 229 /// value is valid for a `MaybeUninit<T>` the compiler can't apply non-zero/niche-filling 230 /// optimizations, potentially resulting in a larger size: 231 /// 232 /// ```rust 233 /// # use std::mem::{MaybeUninit, size_of}; 234 /// assert_eq!(size_of::<Option<bool>>(), 1); 235 /// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2); 236 /// ``` 237 /// 238 /// If `T` is FFI-safe, then so is `MaybeUninit<T>`. 239 /// 240 /// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size, 241 /// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option<T>` and 242 /// `Option<MaybeUninit<T>>` may still have different sizes, and types containing a field of type 243 /// `T` may be laid out (and sized) differently than if that field were `MaybeUninit<T>`. 244 /// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the 245 /// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact 246 /// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not 247 /// remain `#[repr(transparent)]`. That said, `MaybeUninit<T>` will *always* guarantee that it has 248 /// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that 249 /// guarantee may evolve. 250 #[stable(feature = "maybe_uninit", since = "1.36.0")] 251 // Lang item so we can wrap other types in it. This is useful for generators. 252 #[lang = "maybe_uninit"] 253 #[derive(Copy)] 254 #[repr(transparent)] 255 pub union MaybeUninit<T> { 256 uninit: (), 257 value: ManuallyDrop<T>, 258 } 259 260 #[stable(feature = "maybe_uninit", since = "1.36.0")] 261 impl<T: Copy> Clone for MaybeUninit<T> { 262 #[inline(always)] clone(&self) -> Self263 fn clone(&self) -> Self { 264 // Not calling `T::clone()`, we cannot know if we are initialized enough for that. 265 *self 266 } 267 } 268 269 #[stable(feature = "maybe_uninit_debug", since = "1.41.0")] 270 impl<T> fmt::Debug for MaybeUninit<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 272 f.pad(type_name::<Self>()) 273 } 274 } 275 276 impl<T> MaybeUninit<T> { 277 /// Creates a new `MaybeUninit<T>` initialized with the given value. 278 /// It is safe to call [`assume_init`] on the return value of this function. 279 /// 280 /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. 281 /// It is your responsibility to make sure `T` gets dropped if it got initialized. 282 /// 283 /// # Example 284 /// 285 /// ``` 286 /// use std::mem::MaybeUninit; 287 /// 288 /// let v: MaybeUninit<Vec<u8>> = MaybeUninit::new(vec![42]); 289 /// ``` 290 /// 291 /// [`assume_init`]: MaybeUninit::assume_init 292 #[stable(feature = "maybe_uninit", since = "1.36.0")] 293 #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] 294 #[must_use = "use `forget` to avoid running Drop code"] 295 #[inline(always)] new(val: T) -> MaybeUninit<T>296 pub const fn new(val: T) -> MaybeUninit<T> { 297 MaybeUninit { value: ManuallyDrop::new(val) } 298 } 299 300 /// Creates a new `MaybeUninit<T>` in an uninitialized state. 301 /// 302 /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. 303 /// It is your responsibility to make sure `T` gets dropped if it got initialized. 304 /// 305 /// See the [type-level documentation][MaybeUninit] for some examples. 306 /// 307 /// # Example 308 /// 309 /// ``` 310 /// use std::mem::MaybeUninit; 311 /// 312 /// let v: MaybeUninit<String> = MaybeUninit::uninit(); 313 /// ``` 314 #[stable(feature = "maybe_uninit", since = "1.36.0")] 315 #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] 316 #[must_use] 317 #[inline(always)] 318 #[rustc_diagnostic_item = "maybe_uninit_uninit"] uninit() -> MaybeUninit<T>319 pub const fn uninit() -> MaybeUninit<T> { 320 MaybeUninit { uninit: () } 321 } 322 323 /// Create a new array of `MaybeUninit<T>` items, in an uninitialized state. 324 /// 325 /// Note: in a future Rust version this method may become unnecessary 326 /// when Rust allows 327 /// [inline const expressions](https://github.com/rust-lang/rust/issues/76001). 328 /// The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`. 329 /// 330 /// # Examples 331 /// 332 /// ```no_run 333 /// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice)] 334 /// 335 /// use std::mem::MaybeUninit; 336 /// 337 /// extern "C" { 338 /// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize; 339 /// } 340 /// 341 /// /// Returns a (possibly smaller) slice of data that was actually read 342 /// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] { 343 /// unsafe { 344 /// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len()); 345 /// MaybeUninit::slice_assume_init_ref(&buf[..len]) 346 /// } 347 /// } 348 /// 349 /// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array(); 350 /// let data = read(&mut buf); 351 /// ``` 352 #[unstable(feature = "maybe_uninit_uninit_array", issue = "none")] 353 #[rustc_const_unstable(feature = "maybe_uninit_uninit_array", issue = "none")] 354 #[must_use] 355 #[inline(always)] uninit_array<const LEN: usize>() -> [Self; LEN]356 pub const fn uninit_array<const LEN: usize>() -> [Self; LEN] { 357 // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid. 358 unsafe { MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() } 359 } 360 361 /// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being 362 /// filled with `0` bytes. It depends on `T` whether that already makes for 363 /// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized, 364 /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not 365 /// be null. 366 /// 367 /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. 368 /// It is your responsibility to make sure `T` gets dropped if it got initialized. 369 /// 370 /// # Example 371 /// 372 /// Correct usage of this function: initializing a struct with zero, where all 373 /// fields of the struct can hold the bit-pattern 0 as a valid value. 374 /// 375 /// ```rust 376 /// use std::mem::MaybeUninit; 377 /// 378 /// let x = MaybeUninit::<(u8, bool)>::zeroed(); 379 /// let x = unsafe { x.assume_init() }; 380 /// assert_eq!(x, (0, false)); 381 /// ``` 382 /// 383 /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()` 384 /// when `0` is not a valid bit-pattern for the type: 385 /// 386 /// ```rust,no_run 387 /// use std::mem::MaybeUninit; 388 /// 389 /// enum NotZero { One = 1, Two = 2 } 390 /// 391 /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); 392 /// let x = unsafe { x.assume_init() }; 393 /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. 394 /// // This is undefined behavior. ⚠️ 395 /// ``` 396 #[stable(feature = "maybe_uninit", since = "1.36.0")] 397 #[must_use] 398 #[inline] 399 #[rustc_diagnostic_item = "maybe_uninit_zeroed"] zeroed() -> MaybeUninit<T>400 pub fn zeroed() -> MaybeUninit<T> { 401 let mut u = MaybeUninit::<T>::uninit(); 402 // SAFETY: `u.as_mut_ptr()` points to allocated memory. 403 unsafe { 404 u.as_mut_ptr().write_bytes(0u8, 1); 405 } 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)] write(&mut self, val: T) -> &mut T493 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_unstable(feature = "const_maybe_uninit_as_ptr", issue = "75251")] 532 #[inline(always)] as_ptr(&self) -> *const T533 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_ptr", issue = "75251")] 571 #[inline(always)] as_mut_ptr(&mut self) -> *mut T572 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_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] 624 #[inline(always)] 625 #[rustc_diagnostic_item = "assume_init"] 626 #[track_caller] assume_init(self) -> T627 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 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 /// #![feature(maybe_uninit_extra)] 665 /// use std::mem::MaybeUninit; 666 /// 667 /// let mut x = MaybeUninit::<u32>::uninit(); 668 /// x.write(13); 669 /// let x1 = unsafe { x.assume_init_read() }; 670 /// // `u32` is `Copy`, so we may read multiple times. 671 /// let x2 = unsafe { x.assume_init_read() }; 672 /// assert_eq!(x1, x2); 673 /// 674 /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit(); 675 /// x.write(None); 676 /// let x1 = unsafe { x.assume_init_read() }; 677 /// // Duplicating a `None` value is okay, so we may read multiple times. 678 /// let x2 = unsafe { x.assume_init_read() }; 679 /// assert_eq!(x1, x2); 680 /// ``` 681 /// 682 /// *Incorrect* usage of this method: 683 /// 684 /// ```rust,no_run 685 /// #![feature(maybe_uninit_extra)] 686 /// use std::mem::MaybeUninit; 687 /// 688 /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit(); 689 /// x.write(Some(vec![0, 1, 2])); 690 /// let x1 = unsafe { x.assume_init_read() }; 691 /// let x2 = unsafe { x.assume_init_read() }; 692 /// // We now created two copies of the same vector, leading to a double-free ⚠️ when 693 /// // they both get dropped! 694 /// ``` 695 #[unstable(feature = "maybe_uninit_extra", issue = "63567")] 696 #[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")] 697 #[inline(always)] 698 #[track_caller] assume_init_read(&self) -> T699 pub const unsafe fn assume_init_read(&self) -> T { 700 // SAFETY: the caller must guarantee that `self` is initialized. 701 // Reading from `self.as_ptr()` is safe since `self` should be initialized. 702 unsafe { 703 intrinsics::assert_inhabited::<T>(); 704 self.as_ptr().read() 705 } 706 } 707 708 /// Drops the contained value in place. 709 /// 710 /// If you have ownership of the `MaybeUninit`, you can also use 711 /// [`assume_init`] as an alternative. 712 /// 713 /// # Safety 714 /// 715 /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is 716 /// in an initialized state. Calling this when the content is not yet fully 717 /// initialized causes undefined behavior. 718 /// 719 /// On top of that, all additional invariants of the type `T` must be 720 /// satisfied, as the `Drop` implementation of `T` (or its members) may 721 /// rely on this. For example, setting a [`Vec<T>`] to an invalid but 722 /// non-null address makes it initialized (under the current implementation; 723 /// this does not constitute a stable guarantee), because the only 724 /// requirement the compiler knows about it is that the data pointer must be 725 /// non-null. Dropping such a `Vec<T>` however will cause undefined 726 /// behaviour. 727 /// 728 /// [`assume_init`]: MaybeUninit::assume_init 729 /// [`Vec<T>`]: ../../std/vec/struct.Vec.html 730 #[unstable(feature = "maybe_uninit_extra", issue = "63567")] assume_init_drop(&mut self)731 pub unsafe fn assume_init_drop(&mut self) { 732 // SAFETY: the caller must guarantee that `self` is initialized and 733 // satisfies all invariants of `T`. 734 // Dropping the value in place is safe if that is the case. 735 unsafe { ptr::drop_in_place(self.as_mut_ptr()) } 736 } 737 738 /// Gets a shared reference to the contained value. 739 /// 740 /// This can be useful when we want to access a `MaybeUninit` that has been 741 /// initialized but don't have ownership of the `MaybeUninit` (preventing the use 742 /// of `.assume_init()`). 743 /// 744 /// # Safety 745 /// 746 /// Calling this when the content is not yet fully initialized causes undefined 747 /// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really 748 /// is in an initialized state. 749 /// 750 /// # Examples 751 /// 752 /// ### Correct usage of this method: 753 /// 754 /// ```rust 755 /// use std::mem::MaybeUninit; 756 /// 757 /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); 758 /// // Initialize `x`: 759 /// x.write(vec![1, 2, 3]); 760 /// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to 761 /// // create a shared reference to it: 762 /// let x: &Vec<u32> = unsafe { 763 /// // SAFETY: `x` has been initialized. 764 /// x.assume_init_ref() 765 /// }; 766 /// assert_eq!(x, &vec![1, 2, 3]); 767 /// ``` 768 /// 769 /// ### *Incorrect* usages of this method: 770 /// 771 /// ```rust,no_run 772 /// use std::mem::MaybeUninit; 773 /// 774 /// let x = MaybeUninit::<Vec<u32>>::uninit(); 775 /// let x_vec: &Vec<u32> = unsafe { x.assume_init_ref() }; 776 /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ 777 /// ``` 778 /// 779 /// ```rust,no_run 780 /// use std::{cell::Cell, mem::MaybeUninit}; 781 /// 782 /// let b = MaybeUninit::<Cell<bool>>::uninit(); 783 /// // Initialize the `MaybeUninit` using `Cell::set`: 784 /// unsafe { 785 /// b.assume_init_ref().set(true); 786 /// // ^^^^^^^^^^^^^^^ 787 /// // Reference to an uninitialized `Cell<bool>`: UB! 788 /// } 789 /// ``` 790 #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] 791 #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] 792 #[inline(always)] assume_init_ref(&self) -> &T793 pub const unsafe fn assume_init_ref(&self) -> &T { 794 // SAFETY: the caller must guarantee that `self` is initialized. 795 // This also means that `self` must be a `value` variant. 796 unsafe { 797 intrinsics::assert_inhabited::<T>(); 798 &*self.as_ptr() 799 } 800 } 801 802 /// Gets a mutable (unique) reference to the contained value. 803 /// 804 /// This can be useful when we want to access a `MaybeUninit` that has been 805 /// initialized but don't have ownership of the `MaybeUninit` (preventing the use 806 /// of `.assume_init()`). 807 /// 808 /// # Safety 809 /// 810 /// Calling this when the content is not yet fully initialized causes undefined 811 /// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really 812 /// is in an initialized state. For instance, `.assume_init_mut()` cannot be used to 813 /// initialize a `MaybeUninit`. 814 /// 815 /// # Examples 816 /// 817 /// ### Correct usage of this method: 818 /// 819 /// ```rust 820 /// use std::mem::MaybeUninit; 821 /// 822 /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { *buf = [0; 1024] } 823 /// # #[cfg(FALSE)] 824 /// extern "C" { 825 /// /// Initializes *all* the bytes of the input buffer. 826 /// fn initialize_buffer(buf: *mut [u8; 1024]); 827 /// } 828 /// 829 /// let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); 830 /// 831 /// // Initialize `buf`: 832 /// unsafe { initialize_buffer(buf.as_mut_ptr()); } 833 /// // Now we know that `buf` has been initialized, so we could `.assume_init()` it. 834 /// // However, using `.assume_init()` may trigger a `memcpy` of the 1024 bytes. 835 /// // To assert our buffer has been initialized without copying it, we upgrade 836 /// // the `&mut MaybeUninit<[u8; 1024]>` to a `&mut [u8; 1024]`: 837 /// let buf: &mut [u8; 1024] = unsafe { 838 /// // SAFETY: `buf` has been initialized. 839 /// buf.assume_init_mut() 840 /// }; 841 /// 842 /// // Now we can use `buf` as a normal slice: 843 /// buf.sort_unstable(); 844 /// assert!( 845 /// buf.windows(2).all(|pair| pair[0] <= pair[1]), 846 /// "buffer is sorted", 847 /// ); 848 /// ``` 849 /// 850 /// ### *Incorrect* usages of this method: 851 /// 852 /// You cannot use `.assume_init_mut()` to initialize a value: 853 /// 854 /// ```rust,no_run 855 /// use std::mem::MaybeUninit; 856 /// 857 /// let mut b = MaybeUninit::<bool>::uninit(); 858 /// unsafe { 859 /// *b.assume_init_mut() = true; 860 /// // We have created a (mutable) reference to an uninitialized `bool`! 861 /// // This is undefined behavior. ⚠️ 862 /// } 863 /// ``` 864 /// 865 /// For instance, you cannot [`Read`] into an uninitialized buffer: 866 /// 867 /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html 868 /// 869 /// ```rust,no_run 870 /// use std::{io, mem::MaybeUninit}; 871 /// 872 /// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]> 873 /// { 874 /// let mut buffer = MaybeUninit::<[u8; 64]>::uninit(); 875 /// reader.read_exact(unsafe { buffer.assume_init_mut() })?; 876 /// // ^^^^^^^^^^^^^^^^^^^^^^^^ 877 /// // (mutable) reference to uninitialized memory! 878 /// // This is undefined behavior. 879 /// Ok(unsafe { buffer.assume_init() }) 880 /// } 881 /// ``` 882 /// 883 /// Nor can you use direct field access to do field-by-field gradual initialization: 884 /// 885 /// ```rust,no_run 886 /// use std::{mem::MaybeUninit, ptr}; 887 /// 888 /// struct Foo { 889 /// a: u32, 890 /// b: u8, 891 /// } 892 /// 893 /// let foo: Foo = unsafe { 894 /// let mut foo = MaybeUninit::<Foo>::uninit(); 895 /// ptr::write(&mut foo.assume_init_mut().a as *mut u32, 1337); 896 /// // ^^^^^^^^^^^^^^^^^^^^^ 897 /// // (mutable) reference to uninitialized memory! 898 /// // This is undefined behavior. 899 /// ptr::write(&mut foo.assume_init_mut().b as *mut u8, 42); 900 /// // ^^^^^^^^^^^^^^^^^^^^^ 901 /// // (mutable) reference to uninitialized memory! 902 /// // This is undefined behavior. 903 /// foo.assume_init() 904 /// }; 905 /// ``` 906 #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] 907 #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] 908 #[inline(always)] assume_init_mut(&mut self) -> &mut T909 pub const unsafe fn assume_init_mut(&mut self) -> &mut T { 910 // SAFETY: the caller must guarantee that `self` is initialized. 911 // This also means that `self` must be a `value` variant. 912 unsafe { 913 intrinsics::assert_inhabited::<T>(); 914 &mut *self.as_mut_ptr() 915 } 916 } 917 918 /// Extracts the values from an array of `MaybeUninit` containers. 919 /// 920 /// # Safety 921 /// 922 /// It is up to the caller to guarantee that all elements of the array are 923 /// in an initialized state. 924 /// 925 /// # Examples 926 /// 927 /// ``` 928 /// #![feature(maybe_uninit_uninit_array)] 929 /// #![feature(maybe_uninit_array_assume_init)] 930 /// use std::mem::MaybeUninit; 931 /// 932 /// let mut array: [MaybeUninit<i32>; 3] = MaybeUninit::uninit_array(); 933 /// array[0].write(0); 934 /// array[1].write(1); 935 /// array[2].write(2); 936 /// 937 /// // SAFETY: Now safe as we initialised all elements 938 /// let array = unsafe { 939 /// MaybeUninit::array_assume_init(array) 940 /// }; 941 /// 942 /// assert_eq!(array, [0, 1, 2]); 943 /// ``` 944 #[unstable(feature = "maybe_uninit_array_assume_init", issue = "80908")] 945 #[inline(always)] 946 #[track_caller] array_assume_init<const N: usize>(array: [Self; N]) -> [T; N]947 pub 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 (&array as *const _ as *const [T; N]).read() 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 = "const_maybe_uninit_assume_init", issue = "none")] 972 #[inline(always)] slice_assume_init_ref(slice: &[Self]) -> &[T]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)] slice_assume_init_mut(slice: &mut [Self]) -> &mut [T]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)] slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T1005 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)] slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T1013 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, vec_spare_capacity)] 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")] write_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T] where T: Copy,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, vec_spare_capacity)] 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")] write_slice_cloned<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T] where T: Clone,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