|
36 | 36 |
|
37 | 37 | #![stable(feature = "rust1", since = "1.0.0")]
|
38 | 38 |
|
| 39 | +use crate::mem::{self, MaybeUninit}; |
| 40 | +use crate::ptr; |
| 41 | + |
39 | 42 | /// A common trait for the ability to explicitly duplicate an object.
|
40 | 43 | ///
|
41 | 44 | /// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while
|
@@ -204,6 +207,189 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
|
204 | 207 | _field: crate::marker::PhantomData<T>,
|
205 | 208 | }
|
206 | 209 |
|
| 210 | +/// A generalization of [`Clone`] to dynamically-sized types stored in arbitrary containers. |
| 211 | +/// |
| 212 | +/// This trait is implemented for all types implementing [`Clone`], and also [slices](slice) of all |
| 213 | +/// such types. You may also implement this trait to enable cloning trait objects and custom DSTs |
| 214 | +/// (structures containing dynamically-sized fields). |
| 215 | +/// |
| 216 | +/// # Safety |
| 217 | +/// |
| 218 | +/// Implementations must ensure that when `.clone_to_uninit(dst)` returns normally rather than |
| 219 | +/// panicking, it always leaves `*dst` initialized as a valid value of type `Self`. |
| 220 | +/// |
| 221 | +/// # See also |
| 222 | +/// |
| 223 | +/// * [`Clone::clone_from`] is a safe function which may be used instead when `Self` is a [`Sized`] |
| 224 | +/// and the destination is already initialized; it may be able to reuse allocations owned by |
| 225 | +/// the destination. |
| 226 | +/// * [`ToOwned`], which allocates a new destination container. |
| 227 | +/// |
| 228 | +/// [`ToOwned`]: ../../std/borrow/trait.ToOwned.html |
| 229 | +#[unstable(feature = "clone_to_uninit", issue = "126799")] |
| 230 | +pub unsafe trait CloneToUninit { |
| 231 | + /// Performs copy-assignment from `self` to `dst`. |
| 232 | + /// |
| 233 | + /// This is analogous to to `std::ptr::write(dst, self.clone())`, |
| 234 | + /// except that `self` may be a dynamically-sized type ([`!Sized`](Sized)). |
| 235 | + /// |
| 236 | + /// Before this function is called, `dst` may point to uninitialized memory. |
| 237 | + /// After this function is called, `dst` will point to initialized memory; it will be |
| 238 | + /// sound to create a `&Self` reference from the pointer. |
| 239 | + /// |
| 240 | + /// # Safety |
| 241 | + /// |
| 242 | + /// Behavior is undefined if any of the following conditions are violated: |
| 243 | + /// |
| 244 | + /// * `dst` must be [valid] for writes. |
| 245 | + /// * `dst` must be properly aligned. |
| 246 | + /// * `dst` must have the same [pointer metadata] (slice length or `dyn` vtable) as `self`. |
| 247 | + /// |
| 248 | + /// [valid]: ptr#safety |
| 249 | + /// [pointer metadata]: crate::ptr::metadata() |
| 250 | + /// |
| 251 | + /// # Panics |
| 252 | + /// |
| 253 | + /// This function may panic. (For example, it might panic if memory allocation for a clone |
| 254 | + /// of a value owned by `self` fails.) |
| 255 | + /// If the call panics, then `*dst` should be treated as uninitialized memory; it must not be |
| 256 | + /// read or dropped, because even if it was previously valid, it may have been partially |
| 257 | + /// overwritten. |
| 258 | + /// |
| 259 | + /// The caller may also need to take care to deallocate the allocation pointed to by `dst`, |
| 260 | + /// if applicable, to avoid a memory leak, and may need to take other precautions to ensure |
| 261 | + /// soundness in the presence of unwinding. |
| 262 | + /// |
| 263 | + /// Implementors should avoid leaking values by, upon unwinding, dropping all component values |
| 264 | + /// that might have already been created. (For example, if a `[Foo]` of length 3 is being |
| 265 | + /// cloned, and the second of the three calls to `Foo::clone()` unwinds, then the first `Foo` |
| 266 | + /// cloned should be dropped.) |
| 267 | + unsafe fn clone_to_uninit(&self, dst: *mut Self); |
| 268 | +} |
| 269 | + |
| 270 | +#[unstable(feature = "clone_to_uninit", issue = "126799")] |
| 271 | +unsafe impl<T: Clone> CloneToUninit for T { |
| 272 | + default unsafe fn clone_to_uninit(&self, dst: *mut Self) { |
| 273 | + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of |
| 274 | + // ptr::write(). |
| 275 | + unsafe { |
| 276 | + // We hope the optimizer will figure out to create the cloned value in-place, |
| 277 | + // skipping ever storing it on the stack and the copy to the destination. |
| 278 | + ptr::write(dst, self.clone()); |
| 279 | + } |
| 280 | + } |
| 281 | +} |
| 282 | + |
| 283 | +// Specialized implementation for types that are [`Copy`], not just [`Clone`], |
| 284 | +// and can therefore be copied bitwise. |
| 285 | +#[unstable(feature = "clone_to_uninit", issue = "126799")] |
| 286 | +unsafe impl<T: Copy> CloneToUninit for T { |
| 287 | + unsafe fn clone_to_uninit(&self, dst: *mut Self) { |
| 288 | + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of |
| 289 | + // ptr::copy_nonoverlapping(). |
| 290 | + unsafe { |
| 291 | + ptr::copy_nonoverlapping(self, dst, 1); |
| 292 | + } |
| 293 | + } |
| 294 | +} |
| 295 | + |
| 296 | +#[unstable(feature = "clone_to_uninit", issue = "126799")] |
| 297 | +unsafe impl<T: Clone> CloneToUninit for [T] { |
| 298 | + #[cfg_attr(debug_assertions, track_caller)] |
| 299 | + default unsafe fn clone_to_uninit(&self, dst: *mut Self) { |
| 300 | + let len = self.len(); |
| 301 | + // This is the most likely mistake to make, so check it as a debug assertion. |
| 302 | + debug_assert_eq!( |
| 303 | + len, |
| 304 | + dst.len(), |
| 305 | + "clone_to_uninit() source and destination must have equal lengths", |
| 306 | + ); |
| 307 | + |
| 308 | + // SAFETY: The produced `&mut` is valid because: |
| 309 | + // * The caller is obligated to provide a pointer which is valid for writes. |
| 310 | + // * All bytes pointed to are in MaybeUninit, so we don't care about the memory's |
| 311 | + // initialization status. |
| 312 | + let uninit_ref = unsafe { &mut *(dst as *mut [MaybeUninit<T>]) }; |
| 313 | + |
| 314 | + // Copy the elements |
| 315 | + let mut initializing = InitializingSlice::from_fully_uninit(uninit_ref); |
| 316 | + for element_ref in self.iter() { |
| 317 | + // If the clone() panics, `initializing` will take care of the cleanup. |
| 318 | + initializing.push(element_ref.clone()); |
| 319 | + } |
| 320 | + // If we reach here, then the entire slice is initialized, and we've satisfied our |
| 321 | + // responsibilities to the caller. Disarm the cleanup guard by forgetting it. |
| 322 | + mem::forget(initializing); |
| 323 | + } |
| 324 | +} |
| 325 | + |
| 326 | +#[unstable(feature = "clone_to_uninit", issue = "126799")] |
| 327 | +unsafe impl<T: Copy> CloneToUninit for [T] { |
| 328 | + #[cfg_attr(debug_assertions, track_caller)] |
| 329 | + unsafe fn clone_to_uninit(&self, dst: *mut Self) { |
| 330 | + let len = self.len(); |
| 331 | + // This is the most likely mistake to make, so check it as a debug assertion. |
| 332 | + debug_assert_eq!( |
| 333 | + len, |
| 334 | + dst.len(), |
| 335 | + "clone_to_uninit() source and destination must have equal lengths", |
| 336 | + ); |
| 337 | + |
| 338 | + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of |
| 339 | + // ptr::copy_nonoverlapping(). |
| 340 | + unsafe { |
| 341 | + ptr::copy_nonoverlapping(self.as_ptr(), dst.as_mut_ptr(), len); |
| 342 | + } |
| 343 | + } |
| 344 | +} |
| 345 | + |
| 346 | +/// Ownership of a collection of values stored in a non-owned `[MaybeUninit<T>]`, some of which |
| 347 | +/// are not yet initialized. This is sort of like a `Vec` that doesn't own its allocation. |
| 348 | +/// Its responsibility is to provide cleanup on unwind by dropping the values that *are* |
| 349 | +/// initialized, unless disarmed by forgetting. |
| 350 | +/// |
| 351 | +/// This is a helper for `impl<T: Clone> CloneToUninit for [T]`. |
| 352 | +struct InitializingSlice<'a, T> { |
| 353 | + data: &'a mut [MaybeUninit<T>], |
| 354 | + /// Number of elements of `*self.data` that are initialized. |
| 355 | + initialized_len: usize, |
| 356 | +} |
| 357 | + |
| 358 | +impl<'a, T> InitializingSlice<'a, T> { |
| 359 | + #[inline] |
| 360 | + fn from_fully_uninit(data: &'a mut [MaybeUninit<T>]) -> Self { |
| 361 | + Self { data, initialized_len: 0 } |
| 362 | + } |
| 363 | + |
| 364 | + /// Push a value onto the end of the initialized part of the slice. |
| 365 | + /// |
| 366 | + /// # Panics |
| 367 | + /// |
| 368 | + /// Panics if the slice is already fully initialized. |
| 369 | + #[inline] |
| 370 | + fn push(&mut self, value: T) { |
| 371 | + MaybeUninit::write(&mut self.data[self.initialized_len], value); |
| 372 | + self.initialized_len += 1; |
| 373 | + } |
| 374 | +} |
| 375 | + |
| 376 | +impl<'a, T> Drop for InitializingSlice<'a, T> { |
| 377 | + #[cold] // will only be invoked on unwind |
| 378 | + fn drop(&mut self) { |
| 379 | + let initialized_slice = ptr::slice_from_raw_parts_mut( |
| 380 | + MaybeUninit::slice_as_mut_ptr(self.data), |
| 381 | + self.initialized_len, |
| 382 | + ); |
| 383 | + // SAFETY: |
| 384 | + // * the pointer is valid because it was made from a mutable reference |
| 385 | + // * `initialized_len` counts the initialized elements as an invariant of this type, |
| 386 | + // so each of the pointed-to elements is initialized and may be dropped. |
| 387 | + unsafe { |
| 388 | + ptr::drop_in_place::<[T]>(initialized_slice); |
| 389 | + } |
| 390 | + } |
| 391 | +} |
| 392 | + |
207 | 393 | /// Implementations of `Clone` for primitive types.
|
208 | 394 | ///
|
209 | 395 | /// Implementations that cannot be described in Rust
|
|
0 commit comments