|
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,191 @@ 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 implement this trait to allow cloning trait objects and custom DSTs |
| 214 | +/// (structures containing unsized fields). |
| 215 | +/// |
| 216 | +/// # Safety |
| 217 | +/// |
| 218 | +/// Implementations must ensure that `.clone_to_uninit(dst)` always leaves `*dst` initialized |
| 219 | +/// as a valid value of type `Self`, unless it panics. |
| 220 | +/// |
| 221 | +#[unstable(feature = "clone_to_uninit", issue = "none")] |
| 222 | +pub unsafe trait CloneToUninit { |
| 223 | + /// Performs copy-assignment from `self` to `dst`. |
| 224 | + /// |
| 225 | + /// This is analogous to to `std::ptr::write(dst, self.clone())`, |
| 226 | + /// except that `self` may be a dynamically-sized type ([`!Sized`](Sized)). |
| 227 | + /// |
| 228 | + /// Before this function is called, `dst` may point to uninitialized memory. |
| 229 | + /// After this function is called, `dst` will point to initialized memory; it will be |
| 230 | + /// sound to create a `&Self` reference from the pointer. |
| 231 | + /// |
| 232 | + /// # Safety |
| 233 | + /// |
| 234 | + /// Behavior is undefined if any of the following conditions are violated: |
| 235 | + /// |
| 236 | + /// * `dst` must be [valid] for writes. |
| 237 | + /// * `dst` must be properly aligned. |
| 238 | + /// * `dst` must have the same [pointer metadata] (slice length or `dyn` vtable) as `self`. |
| 239 | + /// |
| 240 | + /// [valid]: ptr#safety |
| 241 | + /// [pointer metadata]: crate::ptr::metadata() |
| 242 | + /// |
| 243 | + /// # Panics |
| 244 | + /// |
| 245 | + /// This function may panic. (For example, it might panic if memory allocation for a clone |
| 246 | + /// of a value owned by `self` fails.) |
| 247 | + /// If the call panics, then `*dst` should be treated as uninitialized memory; it must not be |
| 248 | + /// read or dropped, because even if it was previously valid, it may have been partially |
| 249 | + /// overwritten. |
| 250 | + /// |
| 251 | + /// The caller may also need to take care to deallocate the allocation pointed to by `dst`, |
| 252 | + /// if applicable, to avoid a memory leak, and may need to take other precautions to ensure |
| 253 | + /// soundness in the presence of unwinding. |
| 254 | + /// |
| 255 | + /// Implementors should avoid leaking values by, upon unwinding, dropping all component values |
| 256 | + /// that might have already been created. (For example, if a `[Foo]` of length 3 is being |
| 257 | + /// cloned, and the second of the three calls to `Foo::clone()` unwinds, then the first `Foo` |
| 258 | + /// cloned should be dropped.) |
| 259 | + /// |
| 260 | + /// # See also |
| 261 | + /// |
| 262 | + /// * [`Clone::clone_from`] is a safe function which may be used instead when `Self: Sized` |
| 263 | + /// and the destination is aligned. |
| 264 | + /// * [`ToOwned`](std::borrow::ToOwned), which allocates a new destination container. |
| 265 | + unsafe fn clone_to_uninit(&self, dst: *mut Self); |
| 266 | +} |
| 267 | + |
| 268 | +#[unstable(feature = "clone_to_uninit", issue = "none")] |
| 269 | +unsafe impl<T: Clone> CloneToUninit for T { |
| 270 | + default unsafe fn clone_to_uninit(&self, dst: *mut Self) { |
| 271 | + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of |
| 272 | + // ptr::write(). |
| 273 | + unsafe { |
| 274 | + // We hope the optimizer will figure out to create the cloned value in-place, |
| 275 | + // skipping ever storing it on the stack and the copy to the destination. |
| 276 | + ptr::write(dst, self.clone()); |
| 277 | + } |
| 278 | + } |
| 279 | +} |
| 280 | + |
| 281 | +// Specialized implementation for types that are [`Copy`], not just [`Clone`], |
| 282 | +// and can therefore be copied bitwise. |
| 283 | +#[unstable(feature = "clone_to_uninit", issue = "none")] |
| 284 | +unsafe impl<T: Copy> CloneToUninit for T { |
| 285 | + unsafe fn clone_to_uninit(&self, dst: *mut Self) { |
| 286 | + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of |
| 287 | + // ptr::copy_nonoverlapping(). |
| 288 | + unsafe { |
| 289 | + ptr::copy_nonoverlapping(self, dst, 1); |
| 290 | + } |
| 291 | + } |
| 292 | +} |
| 293 | + |
| 294 | +#[unstable(feature = "clone_to_uninit", issue = "none")] |
| 295 | +unsafe impl<T: Clone> CloneToUninit for [T] { |
| 296 | + #[track_caller] |
| 297 | + default unsafe fn clone_to_uninit(&self, dst: *mut Self) { |
| 298 | + let len = self.len(); |
| 299 | + // This is the most likely mistake to make, so check it as a debug assertion, |
| 300 | + // even though the safety contract is that this mistake is UB, because we needed |
| 301 | + // the information anyway. |
| 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 = "none")] |
| 327 | +unsafe impl<T: Copy> CloneToUninit for [T] { |
| 328 | + #[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 | + // even though the safety contract is that this mistake is UB, because we needed |
| 333 | + // the information anyway. |
| 334 | + debug_assert_eq!( |
| 335 | + len, |
| 336 | + dst.len(), |
| 337 | + "clone_to_uninit() source and destination must have equal lengths", |
| 338 | + ); |
| 339 | + |
| 340 | + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of |
| 341 | + // ptr::copy_nonoverlapping(). |
| 342 | + unsafe { |
| 343 | + ptr::copy_nonoverlapping(self.as_ptr(), dst.as_mut_ptr(), len); |
| 344 | + } |
| 345 | + } |
| 346 | +} |
| 347 | + |
| 348 | +/// Ownership of a collection of values stored in a non-owned `[MaybeUninit<T>]`, some of which |
| 349 | +/// are not yet initialized. This is sort of like a `Vec` that doesn't own its allocation. |
| 350 | +/// Its responsibility is to provide cleanup on unwind by dropping the values that *are* |
| 351 | +/// initialized, unless disarmed by forgetting. |
| 352 | +/// |
| 353 | +/// This is a helper for `impl<T: Clone> CloneToUninit for [T]`. |
| 354 | +struct InitializingSlice<'a, T> { |
| 355 | + data: &'a mut [MaybeUninit<T>], |
| 356 | + /// Number of elements of `*self.data` that are initialized. |
| 357 | + initialized_len: usize, |
| 358 | +} |
| 359 | + |
| 360 | +impl<'a, T> InitializingSlice<'a, T> { |
| 361 | + fn from_fully_uninit(data: &'a mut [MaybeUninit<T>]) -> Self { |
| 362 | + Self { data, initialized_len: 0 } |
| 363 | + } |
| 364 | + |
| 365 | + /// Push a value onto the end of the initialized part of the slice. |
| 366 | + /// |
| 367 | + /// # Panics |
| 368 | + /// |
| 369 | + /// Panics if the slice is already fully initialized. |
| 370 | + #[inline] |
| 371 | + fn push(&mut self, value: T) { |
| 372 | + MaybeUninit::write(&mut self.data[self.initialized_len], value); |
| 373 | + self.initialized_len += 1; |
| 374 | + } |
| 375 | +} |
| 376 | + |
| 377 | +impl<'a, T> Drop for InitializingSlice<'a, T> { |
| 378 | + #[cold] // will only be invoked on unwind |
| 379 | + fn drop(&mut self) { |
| 380 | + let initialized_len = mem::take(&mut self.initialized_len); |
| 381 | + let initialized_slice = ptr::slice_from_raw_parts_mut( |
| 382 | + MaybeUninit::slice_as_mut_ptr(self.data).cast::<T>(), |
| 383 | + initialized_len, |
| 384 | + ); |
| 385 | + // SAFETY: |
| 386 | + // * the pointer is valid because it was made from a mutable reference |
| 387 | + // * `initialized_len` counts the initialized elements as an invariant of this type, |
| 388 | + // so each of the pointed-to elements is initialized and may be dropped. |
| 389 | + unsafe { |
| 390 | + ptr::drop_in_place::<[T]>(initialized_slice); |
| 391 | + } |
| 392 | + } |
| 393 | +} |
| 394 | + |
207 | 395 | /// Implementations of `Clone` for primitive types.
|
208 | 396 | ///
|
209 | 397 | /// Implementations that cannot be described in Rust
|
|
0 commit comments