Skip to content

Commit

Permalink
specialize zip: Use associated type for specialized zip struct data
Browse files Browse the repository at this point in the history
The associated type must be 'static to avoid dropck related errors.
  • Loading branch information
bluss committed Jun 14, 2016
1 parent 85cd49f commit 5df05c6
Showing 1 changed file with 39 additions and 13 deletions.
52 changes: 39 additions & 13 deletions src/libcore/iter/mod.rs
Expand Up @@ -301,6 +301,7 @@

use clone::Clone;
use cmp;
use default::Default;
use fmt;
use iter_private::TrustedRandomAccess;
use ops::FnMut;
Expand Down Expand Up @@ -624,8 +625,7 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
pub struct Zip<A, B> {
a: A,
b: B,
index: usize,
len: usize,
spec: <(A, B) as ZipImplData>::Data,
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -667,6 +667,17 @@ trait ZipImpl<A, B> {
B: DoubleEndedIterator + ExactSizeIterator;
}

// Zip specialization data members
#[doc(hidden)]
trait ZipImplData {
type Data: 'static + Clone + Default + fmt::Debug;
}

#[doc(hidden)]
impl<T> ZipImplData for T {
default type Data = ();
}

// General Zip impl
#[doc(hidden)]
impl<A, B> ZipImpl<A, B> for Zip<A, B>
Expand All @@ -677,8 +688,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
Zip {
a: a,
b: b,
index: 0, // not used in general case
len: 0,
spec: Default::default(), // unused
}
}

Expand Down Expand Up @@ -731,6 +741,20 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
}
}

#[doc(hidden)]
#[derive(Default, Debug, Clone)]
struct ZipImplFields {
index: usize,
len: usize,
}

#[doc(hidden)]
impl<A, B> ZipImplData for (A, B)
where A: TrustedRandomAccess, B: TrustedRandomAccess
{
type Data = ZipImplFields;
}

#[doc(hidden)]
impl<A, B> ZipImpl<A, B> for Zip<A, B>
where A: TrustedRandomAccess, B: TrustedRandomAccess
Expand All @@ -740,16 +764,18 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
Zip {
a: a,
b: b,
index: 0,
len: len,
spec: ZipImplFields {
index: 0,
len: len,
}
}
}

#[inline]
fn next(&mut self) -> Option<(A::Item, B::Item)> {
if self.index < self.len {
let i = self.index;
self.index += 1;
if self.spec.index < self.spec.len {
let i = self.spec.index;
self.spec.index += 1;
unsafe {
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
}
Expand All @@ -760,7 +786,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len - self.index;
let len = self.spec.len - self.spec.index;
(len, Some(len))
}

Expand All @@ -769,9 +795,9 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
where A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator
{
if self.index < self.len {
self.len -= 1;
let i = self.len;
if self.spec.index < self.spec.len {
self.spec.len -= 1;
let i = self.spec.len;
unsafe {
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
}
Expand Down

0 comments on commit 5df05c6

Please sign in to comment.