Specialize TrustedLen for Iterator::unzip() · model-checking/verify-rust-std@a86fd0f (original) (raw)

``

1

`+

use super::TrustedLen;

`

``

2

+

1

3

`` /// Conversion from an [Iterator].

``

2

4

`///

`

3

5

`` /// By implementing FromIterator for a type, you define how it will be

``

`@@ -460,6 +462,27 @@ pub trait Extend {

`

460

462

`fn extend_reserve(&mut self, additional: usize) {

`

461

463

`let _ = additional;

`

462

464

`}

`

``

465

+

``

466

`+

/// Extends a collection with one element, without checking there is enough capacity for it.

`

``

467

`+

///

`

``

468

`+

/// # Safety

`

``

469

`+

///

`

``

470

`+

/// For callers: This must only be called when we know the collection has enough capacity

`

``

471

`` +

/// to contain the new item, for example because we previously called extend_reserve.

``

``

472

`+

///

`

``

473

`+

/// For implementors: For a collection to unsafely rely on this method's safety precondition (that is,

`

``

474

`` +

/// invoke UB if they are violated), it must implement extend_reserve correctly. In other words,

``

``

475

`` +

/// callers may assume that if they extend_reserveed enough space they can call this method.

``

``

476

+

``

477

`+

// This method is for internal usage only. It is only on the trait because of specialization's limitations.

`

``

478

`+

#[unstable(feature = "extend_one_unchecked", issue = "none")]

`

``

479

`+

#[doc(hidden)]

`

``

480

`+

unsafe fn extend_one_unchecked(&mut self, item: A)

`

``

481

`+

where

`

``

482

`+

Self: Sized,

`

``

483

`+

{

`

``

484

`+

self.extend_one(item);

`

``

485

`+

}

`

463

486

`}

`

464

487

``

465

488

`#[stable(feature = "extend_for_unit", since = "1.28.0")]

`

`@@ -499,33 +522,102 @@ where

`

499

522

`fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) {

`

500

523

`let (a, b) = self;

`

501

524

`let iter = into_iter.into_iter();

`

``

525

`+

SpecTupleExtend::extend(iter, a, b);

`

``

526

`+

}

`

``

527

+

``

528

`+

fn extend_one(&mut self, item: (A, B)) {

`

``

529

`+

self.0.extend_one(item.0);

`

``

530

`+

self.1.extend_one(item.1);

`

``

531

`+

}

`

``

532

+

``

533

`+

fn extend_reserve(&mut self, additional: usize) {

`

``

534

`+

self.0.extend_reserve(additional);

`

``

535

`+

self.1.extend_reserve(additional);

`

``

536

`+

}

`

``

537

+

``

538

`+

unsafe fn extend_one_unchecked(&mut self, item: (A, B)) {

`

``

539

`` +

// SAFETY: Those are our safety preconditions, and we correctly forward extend_reserve.

``

``

540

`+

unsafe {

`

``

541

`+

self.0.extend_one_unchecked(item.0);

`

``

542

`+

self.1.extend_one_unchecked(item.1);

`

``

543

`+

}

`

``

544

`+

}

`

``

545

`+

}

`

``

546

+

``

547

`+

fn default_extend_tuple<A, B, ExtendA, ExtendB>(

`

``

548

`+

iter: impl Iterator<Item = (A, B)>,

`

``

549

`+

a: &mut ExtendA,

`

``

550

`+

b: &mut ExtendB,

`

``

551

`+

) where

`

``

552

`+

ExtendA: Extend,

`

``

553

`+

ExtendB: Extend,

`

``

554

`+

{

`

``

555

`+

fn extend<'a, A, B>(

`

``

556

`+

a: &'a mut impl Extend,

`

``

557

`+

b: &'a mut impl Extend,

`

``

558

`+

) -> impl FnMut((), (A, B)) + 'a {

`

``

559

`+

move |(), (t, u)| {

`

``

560

`+

a.extend_one(t);

`

``

561

`+

b.extend_one(u);

`

``

562

`+

}

`

``

563

`+

}

`

``

564

+

``

565

`+

let (lower_bound, _) = iter.size_hint();

`

``

566

`+

if lower_bound > 0 {

`

``

567

`+

a.extend_reserve(lower_bound);

`

``

568

`+

b.extend_reserve(lower_bound);

`

``

569

`+

}

`

``

570

+

``

571

`+

iter.fold((), extend(a, b));

`

``

572

`+

}

`

``

573

+

``

574

`+

trait SpecTupleExtend<A, B> {

`

``

575

`+

fn extend(self, a: &mut A, b: &mut B);

`

``

576

`+

}

`

502

577

``

``

578

`+

impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter

`

``

579

`+

where

`

``

580

`+

ExtendA: Extend,

`

``

581

`+

ExtendB: Extend,

`

``

582

`+

Iter: Iterator<Item = (A, B)>,

`

``

583

`+

{

`

``

584

`+

default fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {

`

``

585

`+

default_extend_tuple(self, a, b);

`

``

586

`+

}

`

``

587

`+

}

`

``

588

+

``

589

`+

impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter

`

``

590

`+

where

`

``

591

`+

ExtendA: Extend,

`

``

592

`+

ExtendB: Extend,

`

``

593

`+

Iter: TrustedLen<Item = (A, B)>,

`

``

594

`+

{

`

``

595

`+

fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {

`

503

596

`fn extend<'a, A, B>(

`

504

597

`a: &'a mut impl Extend,

`

505

598

`b: &'a mut impl Extend,

`

506

599

`) -> impl FnMut((), (A, B)) + 'a {

`

507

``

`-

move |(), (t, u)| {

`

508

``

`-

a.extend_one(t);

`

509

``

`-

b.extend_one(u);

`

``

600

`` +

// SAFETY: We reserve enough space for the size_hint, and the iterator is TrustedLen

``

``

601

`` +

// so its size_hint is exact.

``

``

602

`+

move |(), (t, u)| unsafe {

`

``

603

`+

a.extend_one_unchecked(t);

`

``

604

`+

b.extend_one_unchecked(u);

`

510

605

`}

`

511

606

`}

`

512

607

``

513

``

`-

let (lower_bound, _) = iter.size_hint();

`

``

608

`+

let (lower_bound, upper_bound) = self.size_hint();

`

``

609

+

``

610

`+

if upper_bound.is_none() {

`

``

611

`` +

// We cannot reserve more than usize::MAX items, and this is likely to go out of memory anyway.

``

``

612

`+

default_extend_tuple(self, a, b);

`

``

613

`+

return;

`

``

614

`+

}

`

``

615

+

514

616

`if lower_bound > 0 {

`

515

617

` a.extend_reserve(lower_bound);

`

516

618

` b.extend_reserve(lower_bound);

`

517

619

`}

`

518

620

``

519

``

`-

iter.fold((), extend(a, b));

`

520

``

`-

}

`

521

``

-

522

``

`-

fn extend_one(&mut self, item: (A, B)) {

`

523

``

`-

self.0.extend_one(item.0);

`

524

``

`-

self.1.extend_one(item.1);

`

525

``

`-

}

`

526

``

-

527

``

`-

fn extend_reserve(&mut self, additional: usize) {

`

528

``

`-

self.0.extend_reserve(additional);

`

529

``

`-

self.1.extend_reserve(additional);

`

``

621

`+

self.fold((), extend(a, b));

`

530

622

`}

`

531

623

`}

`