Add core::clone::CloneToUninit. · rust-lang/rust@ec201b8 (original) (raw)

`@@ -36,6 +36,9 @@

`

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:📑:PhantomData,

`

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 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).

``

``

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]) };

`

``

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],

`

``

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]) -> 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

`