|
36 | 36 |
|
37 | 37 | #![stable(feature = "rust1", since = "1.0.0")] |
38 | 38 |
|
| 39 | +usecrate::mem::{self,MaybeUninit}; |
| 40 | +usecrate::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 | +pubunsafetraitCloneToUninit{ |
| 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 | +unsafefnclone_to_uninit(&self,dst:*mutSelf); |
| 268 | +} |
| 269 | + |
| 270 | +#[unstable(feature = "clone_to_uninit", issue = "126799")] |
| 271 | +unsafeimpl<T:Clone>CloneToUninitforT{ |
| 272 | +defaultunsafefnclone_to_uninit(&self,dst:*mutSelf){ |
| 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 | +unsafeimpl<T:Copy>CloneToUninitforT{ |
| 287 | +unsafefnclone_to_uninit(&self,dst:*mutSelf){ |
| 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 | +unsafeimpl<T:Clone>CloneToUninitfor[T]{ |
| 298 | +#[cfg_attr(debug_assertions, track_caller)] |
| 299 | +defaultunsafefnclone_to_uninit(&self,dst:*mutSelf){ |
| 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 | +letmut initializing = InitializingSlice::from_fully_uninit(uninit_ref); |
| 316 | +for element_ref inself.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 | +unsafeimpl<T:Copy>CloneToUninitfor[T]{ |
| 328 | +#[cfg_attr(debug_assertions, track_caller)] |
| 329 | +unsafefnclone_to_uninit(&self,dst:*mutSelf){ |
| 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 | +structInitializingSlice<'a,T>{ |
| 353 | +data:&'amut[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 | +fnfrom_fully_uninit(data:&'amut[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 | +fnpush(&mutself,value:T){ |
| 371 | +MaybeUninit::write(&mutself.data[self.initialized_len], value); |
| 372 | +self.initialized_len += 1; |
| 373 | +} |
| 374 | +} |
| 375 | + |
| 376 | +impl<'a,T>DropforInitializingSlice<'a,T>{ |
| 377 | +#[cold]// will only be invoked on unwind |
| 378 | +fndrop(&mutself){ |
| 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