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_reserve
ed 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
`}
`