Repository: rust-itertools/itertools (language: rust)

Issue:
Make TupleCollect public
Currently the tuple collect trait is crate internal which makes it impossible to refer to it in a function. I was trying to wrap tuple collect but this is now not possible.


Discussion / hints:

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index 70816d165..6e9837dc3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -137,6 +137,12 @@ pub mod structs {
     pub use zip_longest::ZipLongest;
     pub use ziptuple::Zip;
 }
+
+/// Traits helpful for using certain `Itertools` methods in generic contexts.
+pub mod traits {
+    pub use ::tuple_impl::HomogeneousTuple;
+}
+
 #[allow(deprecated)]
 pub use structs::*;
 pub use concat_impl::concat;
@@ -588,7 +594,7 @@ pub trait Itertools : Iterator {
     /// ```
     fn tuple_windows<T>(self) -> TupleWindows<Self, T>
         where Self: Sized + Iterator<Item = T::Item>,
-              T: tuple_impl::TupleCollect,
+              T: traits::HomogeneousTuple,
               T::Item: Clone
     {
         tuple_impl::tuple_windows(self)
@@ -627,7 +633,7 @@ pub trait Itertools : Iterator {
     /// See also [`Tuples::into_buffer`](structs/struct.Tuples.html#method.into_buffer).
     fn tuples<T>(self) -> Tuples<Self, T>
         where Self: Sized + Iterator<Item = T::Item>,
-              T: tuple_impl::TupleCollect
+              T: traits::HomogeneousTuple
     {
         tuple_impl::tuples(self)
     }
@@ -1352,7 +1358,7 @@ pub trait Itertools : Iterator {
     /// ```
     fn next_tuple<T>(&mut self) -> Option<T>
         where Self: Sized + Iterator<Item = T::Item>,
-              T: tuple_impl::TupleCollect
+              T: traits::HomogeneousTuple
     {
         T::collect_from_iter_no_buf(self)
     }
@@ -1377,7 +1383,7 @@ pub trait Itertools : Iterator {
     /// ```
     fn collect_tuple<T>(mut self) -> Option<T>
         where Self: Sized + Iterator<Item = T::Item>,
-              T: tuple_impl::TupleCollect
+              T: traits::HomogeneousTuple
     {
         match self.next_tuple() {
             elt @ Some(_) => match self.next() {
diff --git a/src/tuple_impl.rs b/src/tuple_impl.rs
index 0daa7800c..51e139fe4 100644
--- a/src/tuple_impl.rs
+++ b/src/tuple_impl.rs
@@ -2,20 +2,32 @@
 
 use std::iter::Fuse;
 
+// `HomogeneousTuple` is a public facade for `TupleCollect`, allowing
+// tuple-related methods to be used by clients in generic contexts, while
+// hiding the implementation details of `TupleCollect`.
+// See https://github.com/rust-itertools/itertools/issues/387
+
+/// Implemented for homogeneous tuples of size up to 4.
+pub trait HomogeneousTuple
+    : TupleCollect
+{}
+
+impl<T: TupleCollect> HomogeneousTuple for T {}
+
 /// An iterator over a incomplete tuple.
 ///
 /// See [`.tuples()`](../trait.Itertools.html#method.tuples) and
 /// [`Tuples::into_buffer()`](struct.Tuples.html#method.into_buffer).
 #[derive(Debug)]
 pub struct TupleBuffer<T>
-    where T: TupleCollect
+    where T: HomogeneousTuple
 {
     cur: usize,
     buf: T::Buffer,
 }
 
 impl<T> TupleBuffer<T>
-    where T: TupleCollect
+    where T: HomogeneousTuple
 {
     fn new(buf: T::Buffer) -> Self {
         TupleBuffer {
@@ -26,7 +38,7 @@ impl<T> TupleBuffer<T>
 }
 
 impl<T> Iterator for TupleBuffer<T>
-    where T: TupleCollect
+    where T: HomogeneousTuple
 {
     type Item = T::Item;
 
@@ -54,7 +66,7 @@ impl<T> Iterator for TupleBuffer<T>
 }
 
 impl<T> ExactSizeIterator for TupleBuffer<T>
-    where T: TupleCollect
+    where T: HomogeneousTuple
 {
 }
 
@@ -64,7 +76,7 @@ impl<T> ExactSizeIterator for TupleBuffer<T>
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 pub struct Tuples<I, T>
     where I: Iterator<Item = T::Item>,
-          T: TupleCollect
+          T: HomogeneousTuple
 {
     iter: Fuse<I>,
     buf: T::Buffer,
@@ -73,7 +85,7 @@ pub struct Tuples<I, T>
 /// Create a new tuples iterator.
 pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
     where I: Iterator<Item = T::Item>,
-          T: TupleCollect
+          T: HomogeneousTuple
 {
     Tuples {
         iter: iter.fuse(),
@@ -83,7 +95,7 @@ pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
 
 impl<I, T> Iterator for Tuples<I, T>
     where I: Iterator<Item = T::Item>,
-          T: TupleCollect
+          T: HomogeneousTuple
 {
     type Item = T;
 
@@ -94,7 +106,7 @@ impl<I, T> Iterator for Tuples<I, T>
 
 impl<I, T> Tuples<I, T>
     where I: Iterator<Item = T::Item>,
-          T: TupleCollect
+          T: HomogeneousTuple
 {
     /// Return a buffer with the produced items that was not enough to be grouped in a tuple.
     ///
@@ -120,7 +132,7 @@ impl<I, T> Tuples<I, T>
 #[derive(Debug)]
 pub struct TupleWindows<I, T>
     where I: Iterator<Item = T::Item>,
-          T: TupleCollect
+          T: HomogeneousTuple
 {
     iter: I,
     last: Option<T>,
@@ -129,7 +141,7 @@ pub struct TupleWindows<I, T>
 /// Create a new tuple windows iterator.
 pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T>
     where I: Iterator<Item = T::Item>,
-          T: TupleCollect,
+          T: HomogeneousTuple,
           T::Item: Clone
 {
     use std::iter::once;
@@ -152,7 +164,7 @@ pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T>
 
 impl<I, T> Iterator for TupleWindows<I, T>
     where I: Iterator<Item = T::Item>,
-          T: TupleCollect + Clone,
+          T: HomogeneousTuple + Clone,
           T::Item: Clone
 {
     type Item = T;


Test patch: