CloneToUninit: use a private specialization trait · patricklam/verify-rust-std@569ab6a (original) (raw)

`@@ -36,8 +36,7 @@

`

36

36

``

37

37

`#![stable(feature = "rust1", since = "1.0.0")]

`

38

38

``

39

``

`-

use crate::mem::{self, MaybeUninit};

`

40

``

`-

use crate::ptr;

`

``

39

`+

mod uninit;

`

41

40

``

42

41

`/// A common trait for the ability to explicitly duplicate an object.

`

43

42

`///

`

`@@ -248,7 +247,7 @@ pub unsafe trait CloneToUninit {

`

248

247

`` /// * dst must be properly aligned.

``

249

248

`` /// * dst must have the same [pointer metadata] (slice length or dyn vtable) as self.

``

250

249

`///

`

251

``

`-

/// [valid]: ptr#safety

`

``

250

`+

/// [valid]: crate::ptr#safety

`

252

251

`/// [pointer metadata]: crate::ptr::metadata()

`

253

252

`///

`

254

253

`/// # Panics

`

`@@ -272,83 +271,20 @@ pub unsafe trait CloneToUninit {

`

272

271

``

273

272

`#[unstable(feature = "clone_to_uninit", issue = "126799")]

`

274

273

`unsafe impl<T: Clone> CloneToUninit for T {

`

275

``

`-

#[inline]

`

276

``

`-

default unsafe fn clone_to_uninit(&self, dst: *mut Self) {

`

277

``

`-

// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of

`

278

``

`-

// ptr::write().

`

279

``

`-

unsafe {

`

280

``

`-

// We hope the optimizer will figure out to create the cloned value in-place,

`

281

``

`-

// skipping ever storing it on the stack and the copy to the destination.

`

282

``

`-

ptr::write(dst, self.clone());

`

283

``

`-

}

`

284

``

`-

}

`

285

``

`-

}

`

286

``

-

287

``

`` -

// Specialized implementation for types that are [Copy], not just [Clone],

``

288

``

`-

// and can therefore be copied bitwise.

`

289

``

`-

#[doc(hidden)]

`

290

``

`-

#[unstable(feature = "clone_to_uninit", issue = "126799")]

`

291

``

`-

unsafe impl<T: Copy> CloneToUninit for T {

`

292

274

`#[inline]

`

293

275

`unsafe fn clone_to_uninit(&self, dst: *mut Self) {

`

294

``

`-

// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of

`

295

``

`-

// ptr::copy_nonoverlapping().

`

296

``

`-

unsafe {

`

297

``

`-

ptr::copy_nonoverlapping(self, dst, 1);

`

298

``

`-

}

`

``

276

`+

// SAFETY: we're calling a specialization with the same contract

`

``

277

`+

unsafe { ::clone_one(self, dst) }

`

299

278

`}

`

300

279

`}

`

301

280

``

302

281

`#[unstable(feature = "clone_to_uninit", issue = "126799")]

`

303

282

`unsafe impl<T: Clone> CloneToUninit for [T] {

`

304

``

`-

#[inline]

`

305

``

`-

#[cfg_attr(debug_assertions, track_caller)]

`

306

``

`-

default unsafe fn clone_to_uninit(&self, dst: *mut Self) {

`

307

``

`-

let len = self.len();

`

308

``

`-

// This is the most likely mistake to make, so check it as a debug assertion.

`

309

``

`-

debug_assert_eq!(

`

310

``

`-

len,

`

311

``

`-

dst.len(),

`

312

``

`-

"clone_to_uninit() source and destination must have equal lengths",

`

313

``

`-

);

`

314

``

-

315

``

`` -

// SAFETY: The produced &mut is valid because:

``

316

``

`-

// * The caller is obligated to provide a pointer which is valid for writes.

`

317

``

`-

// * All bytes pointed to are in MaybeUninit, so we don't care about the memory's

`

318

``

`-

// initialization status.

`

319

``

`-

let uninit_ref = unsafe { &mut *(dst as *mut [MaybeUninit]) };

`

320

``

-

321

``

`-

// Copy the elements

`

322

``

`-

let mut initializing = InitializingSlice::from_fully_uninit(uninit_ref);

`

323

``

`-

for element_ref in self.iter() {

`

324

``

`` -

// If the clone() panics, initializing will take care of the cleanup.

``

325

``

`-

initializing.push(element_ref.clone());

`

326

``

`-

}

`

327

``

`-

// If we reach here, then the entire slice is initialized, and we've satisfied our

`

328

``

`-

// responsibilities to the caller. Disarm the cleanup guard by forgetting it.

`

329

``

`-

mem::forget(initializing);

`

330

``

`-

}

`

331

``

`-

}

`

332

``

-

333

``

`-

#[doc(hidden)]

`

334

``

`-

#[unstable(feature = "clone_to_uninit", issue = "126799")]

`

335

``

`-

unsafe impl<T: Copy> CloneToUninit for [T] {

`

336

283

`#[inline]

`

337

284

`#[cfg_attr(debug_assertions, track_caller)]

`

338

285

`unsafe fn clone_to_uninit(&self, dst: *mut Self) {

`

339

``

`-

let len = self.len();

`

340

``

`-

// This is the most likely mistake to make, so check it as a debug assertion.

`

341

``

`-

debug_assert_eq!(

`

342

``

`-

len,

`

343

``

`-

dst.len(),

`

344

``

`-

"clone_to_uninit() source and destination must have equal lengths",

`

345

``

`-

);

`

346

``

-

347

``

`-

// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of

`

348

``

`-

// ptr::copy_nonoverlapping().

`

349

``

`-

unsafe {

`

350

``

`-

ptr::copy_nonoverlapping(self.as_ptr(), dst.as_mut_ptr(), len);

`

351

``

`-

}

`

``

286

`+

// SAFETY: we're calling a specialization with the same contract

`

``

287

`+

unsafe { ::clone_slice(self, dst) }

`

352

288

`}

`

353

289

`}

`

354

290

``

`@@ -374,53 +310,6 @@ unsafe impl CloneToUninit for crate::ffi::CStr {

`

374

310

`}

`

375

311

`}

`

376

312

``

377

``

`` -

/// Ownership of a collection of values stored in a non-owned [MaybeUninit<T>], some of which

``

378

``

`` -

/// are not yet initialized. This is sort of like a Vec that doesn't own its allocation.

``

379

``

`-

/// Its responsibility is to provide cleanup on unwind by dropping the values that are

`

380

``

`-

/// initialized, unless disarmed by forgetting.

`

381

``

`-

///

`

382

``

`` -

/// This is a helper for impl<T: Clone> CloneToUninit for [T].

``

383

``

`-

struct InitializingSlice<'a, T> {

`

384

``

`-

data: &'a mut [MaybeUninit],

`

385

``

`` -

/// Number of elements of *self.data that are initialized.

``

386

``

`-

initialized_len: usize,

`

387

``

`-

}

`

388

``

-

389

``

`-

impl<'a, T> InitializingSlice<'a, T> {

`

390

``

`-

#[inline]

`

391

``

`-

fn from_fully_uninit(data: &'a mut [MaybeUninit]) -> Self {

`

392

``

`-

Self { data, initialized_len: 0 }

`

393

``

`-

}

`

394

``

-

395

``

`-

/// Push a value onto the end of the initialized part of the slice.

`

396

``

`-

///

`

397

``

`-

/// # Panics

`

398

``

`-

///

`

399

``

`-

/// Panics if the slice is already fully initialized.

`

400

``

`-

#[inline]

`

401

``

`-

fn push(&mut self, value: T) {

`

402

``

`-

MaybeUninit::write(&mut self.data[self.initialized_len], value);

`

403

``

`-

self.initialized_len += 1;

`

404

``

`-

}

`

405

``

`-

}

`

406

``

-

407

``

`-

impl<'a, T> Drop for InitializingSlice<'a, T> {

`

408

``

`-

#[cold] // will only be invoked on unwind

`

409

``

`-

fn drop(&mut self) {

`

410

``

`-

let initialized_slice = ptr::slice_from_raw_parts_mut(

`

411

``

`-

MaybeUninit::slice_as_mut_ptr(self.data),

`

412

``

`-

self.initialized_len,

`

413

``

`-

);

`

414

``

`-

// SAFETY:

`

415

``

`-

// * the pointer is valid because it was made from a mutable reference

`

416

``

`` -

// * initialized_len counts the initialized elements as an invariant of this type,

``

417

``

`-

// so each of the pointed-to elements is initialized and may be dropped.

`

418

``

`-

unsafe {

`

419

``

`-

ptr::drop_in_place::<[T]>(initialized_slice);

`

420

``

`-

}

`

421

``

`-

}

`

422

``

`-

}

`

423

``

-

424

313

`` /// Implementations of Clone for primitive types.

``

425

314

`///

`

426

315

`/// Implementations that cannot be described in Rust

`