From 5df05c6e221b718e82c87003e8b078a9cdbefb70 Mon Sep 17 00:00:00 2001
From: Ulrik Sverdrup <bluss@users.noreply.github.com>
Date: Fri, 22 Apr 2016 18:47:42 +0200
Subject: [PATCH] specialize zip: Use associated type for specialized zip
 struct data

The associated type must be 'static to avoid dropck related errors.
---
 src/libcore/iter/mod.rs | 52 ++++++++++++++++++++++++++++++-----------
 1 file changed, 39 insertions(+), 13 deletions(-)

diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 1a2d8e57e86..b866655bbd5 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -301,6 +301,7 @@
 
 use clone::Clone;
 use cmp;
+use default::Default;
 use fmt;
 use iter_private::TrustedRandomAccess;
 use ops::FnMut;
@@ -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")]
@@ -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>
@@ -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
         }
     }
 
@@ -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
@@ -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)))
             }
@@ -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))
     }
 
@@ -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)))
             }