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

Issue:
Use `alloc` instead of `std` if supported

more no_std support
Although itertools have no_std support it lacks implementations of most usfeful functions like collect_vec, sorted_by() etc in no_std mode. From my tests it seems that implementing it should be fairly easy, and I will try to contribute with solution.



Discussion / hints:

What do you have in mind? `Vec` is not available in `#[no_std]` contexts.
So add alloc as dependency while in no_std. Most programs that use no_std already use alloc 
This will require adding new feature `no_std` so alloc can be included only there, and change 
`#[cfg(not(feature = "use_std"))]` to `
#[cfg(feature = "no_std")]`
I can assure you that most no_std programs do not use alloc

On Thu, Aug 20, 2020 at 3:11 PM Michał Majda <notifications@github.com>
wrote:

> This will require adding new feature no_std so alloc can be included only
> there, and change
> #[cfg(not(feature = "use_std"))] to #[cfg(feature = "no_std")]
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/rust-itertools/itertools/issues/470#issuecomment-677932678>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AADPI5FCBIJTTVLV4QPNI5TSBWNQBANCNFSM4QGUL6IQ>
> .
>

Still I think alloc is most reasonable option here, however I am still a beginner so I don't know other good options.
> This will require adding new feature `no_std` so alloc can be included only there, and change
> `#[cfg(not(feature = "use_std"))]` to ` #[cfg(feature = "no_std")]`

That doesn't sound quite right to me. Crate features should add functionality, not remove it.

A better approach would be to add a `use_alloc` feature and change [this line](https://github.com/rust-itertools/itertools/blob/master/Cargo.toml#L41) to:
```
use_std = ["use_alloc"]
```
...and to change [this line](https://github.com/rust-itertools/itertools/blob/89f3a0dafc372786cacb91d0e30c97b1d9dcb2d9/Cargo.toml#L40) to:
```
default = ["use_alloc"]
```

(I don't think we currently use *any* std-only features, so this won't be a breaking change.)

@zendurix Are you actually programming in an environment that has `alloc` but not `std`?
I am working on adding no_std feature to project, and I am already using alloc there. I think tomorrow (at my time) I will try to add and test this feature and if it works fine I will make PR. 
use_alloc feature sounds good, even nalgebra has feature alloc and propably many more
I think default should stay like this:
` default = ["use_std"]`
And I don't see reason to use alloc in std. 
I think best option (most crates do this like this) is to use `std` as default and `alloc` as optional feature.
I have made functional PR but I have accidentally used `cargo fmt` (because of good habbit :p). And I saw that you have this disabled. Should I restore code to previous formatting? (It have to be manual work though :/)
I have uploaded PR
https://github.com/rust-itertools/itertools/pull/471

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index 276d13aec..0811ef0dc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,15 +2,17 @@ language: rust
 sudo: false
 matrix:
   include:
-    - rust: 1.32.0
+    - rust: 1.36.0
       script:
         - |
             cargo build --verbose --no-default-features &&
+            cargo build --verbose --no-default-features --features "use_alloc" &&
             cargo build --verbose --features "$FEATURES"
     - rust: stable
       script:
         - |
             cargo build --verbose --no-default-features &&
+            cargo build --verbose --no-default-features --features "use_alloc" &&
             cargo build --verbose --features "$FEATURES" &&
             cargo test --verbose --features "$FEATURES" &&
             cargo bench --no-run --verbose --features "$FEATURES"
@@ -18,6 +20,7 @@ matrix:
       script:
         - |
             cargo build --verbose --no-default-features &&
+            cargo build --verbose --no-default-features --features "use_alloc" &&
             cargo build --verbose --features "$FEATURES" &&
             cargo test --verbose --features "$FEATURES" &&
             cargo bench --no-run --verbose --features "$FEATURES"
diff --git a/Cargo.toml b/Cargo.toml
index 3ec0f56f8..3de576bc3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -38,7 +38,8 @@ version = "0.2"
 
 [features]
 default = ["use_std"]
-use_std = []
+use_std = ["use_alloc"]
+use_alloc = []
 
 [profile]
 bench = { debug = true }
diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs
index 0b9d1185f..e77bbf032 100644
--- a/src/adaptors/mod.rs
+++ b/src/adaptors/mod.rs
@@ -11,7 +11,7 @@ pub use self::coalesce::*;
 pub use self::map::{map_into, map_ok, MapInto, MapOk};
 #[allow(deprecated)]
 pub use self::map::MapResults;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 pub use self::multi_product::*;
 
 use std::fmt;
diff --git a/src/adaptors/multi_product.rs b/src/adaptors/multi_product.rs
index 532333a48..6938014ce 100644
--- a/src/adaptors/multi_product.rs
+++ b/src/adaptors/multi_product.rs
@@ -1,8 +1,10 @@
-#![cfg(feature = "use_std")]
+#![cfg(feature = "use_alloc")]
 
 use crate::size_hint;
 use crate::Itertools;
 
+use alloc::vec::Vec;
+
 #[derive(Clone)]
 /// An iterator adaptor that iterates over the cartesian product of
 /// multiple iterators of type `I`.
diff --git a/src/combinations.rs b/src/combinations.rs
index a8b612f17..9231a7b41 100644
--- a/src/combinations.rs
+++ b/src/combinations.rs
@@ -1,6 +1,7 @@
 use std::fmt;
 
 use super::lazy_buffer::LazyBuffer;
+use alloc::vec::Vec;
 
 /// An iterator to iterate through all the `k`-length combinations in an iterator.
 ///
diff --git a/src/combinations_with_replacement.rs b/src/combinations_with_replacement.rs
index d51154521..38556c039 100644
--- a/src/combinations_with_replacement.rs
+++ b/src/combinations_with_replacement.rs
@@ -1,3 +1,4 @@
+use alloc::vec::Vec;
 use std::fmt;
 
 use super::lazy_buffer::LazyBuffer;
@@ -44,7 +45,7 @@ where
     I: Iterator,
     I::Item: Clone,
 {
-    let indices: Vec<usize> = vec![0; k];
+    let indices: Vec<usize> = alloc::vec![0; k];
     let pool: LazyBuffer<I> = LazyBuffer::new(iter);
 
     CombinationsWithReplacement {
diff --git a/src/free.rs b/src/free.rs
index a9008537b..bfc5ab422 100644
--- a/src/free.rs
+++ b/src/free.rs
@@ -3,13 +3,18 @@
 //! The benefit of free functions is that they accept any `IntoIterator` as
 //! argument, so the resulting code may be easier to read.
 
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 use std::fmt::Display;
 use std::iter::{self, Zip};
-#[cfg(feature = "use_std")]
-type VecIntoIter<T> = ::std::vec::IntoIter<T>;
+#[cfg(feature = "use_alloc")]
+type VecIntoIter<T> = alloc::vec::IntoIter<T>;
 
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
+use alloc::{
+    string::String,
+};
+
+#[cfg(feature = "use_alloc")]
 use crate::Itertools;
 
 pub use crate::adaptors::{
@@ -17,17 +22,17 @@ pub use crate::adaptors::{
     merge,
     put_back,
 };
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 pub use crate::put_back_n_impl::put_back_n;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 pub use crate::multipeek_impl::multipeek;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 pub use crate::peek_nth::peek_nth;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 pub use crate::kmerge_impl::kmerge;
 pub use crate::zip_eq_impl::zip_eq;
 pub use crate::merge_join::merge_join_by;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 pub use crate::rciter_impl::rciter;
 
 /// Iterate `iterable` with a running index.
@@ -208,7 +213,7 @@ pub fn min<I>(iterable: I) -> Option<I::Item>
 ///
 /// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3");
 /// ```
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 pub fn join<I>(iterable: I, sep: &str) -> String
     where I: IntoIterator,
           I::Item: Display
@@ -228,7 +233,7 @@ pub fn join<I>(iterable: I, sep: &str) -> String
 ///
 /// assert_equal(sorted("rust".chars()), "rstu".chars());
 /// ```
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 pub fn sorted<I>(iterable: I) -> VecIntoIter<I::Item>
     where I: IntoIterator,
           I::Item: Ord
diff --git a/src/groupbylazy.rs b/src/groupbylazy.rs
index bf6e3c7a1..5d4a0c92e 100644
--- a/src/groupbylazy.rs
+++ b/src/groupbylazy.rs
@@ -1,5 +1,5 @@
 use std::cell::{Cell, RefCell};
-use std::vec;
+use alloc::vec::{self, Vec};
 
 /// A trait to unify FnMut for GroupBy with the chunk key in IntoChunks
 trait KeyFunction<A> {
diff --git a/src/kmerge_impl.rs b/src/kmerge_impl.rs
index 8f68aeb25..a1b3d8e6c 100644
--- a/src/kmerge_impl.rs
+++ b/src/kmerge_impl.rs
@@ -1,6 +1,7 @@
 use crate::size_hint;
 use crate::Itertools;
 
+use alloc::vec::Vec;
 use std::mem::replace;
 use std::fmt;
 
diff --git a/src/lazy_buffer.rs b/src/lazy_buffer.rs
index 01123d473..931755aa5 100644
--- a/src/lazy_buffer.rs
+++ b/src/lazy_buffer.rs
@@ -1,4 +1,5 @@
 use std::ops::Index;
+use alloc::vec::Vec;
 
 #[derive(Debug, Clone)]
 pub struct LazyBuffer<I: Iterator> {
diff --git a/src/lib.rs b/src/lib.rs
index 4c10178fd..00264e466 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -50,6 +50,15 @@
 #[cfg(not(feature = "use_std"))]
 extern crate core as std;
 
+#[cfg(feature = "use_alloc")]
+extern crate alloc;
+
+#[cfg(feature = "use_alloc")]
+use alloc::{
+    string::String,
+    vec::Vec,
+};
+
 pub use either::Either;
 
 #[cfg(feature = "use_std")]
@@ -59,11 +68,11 @@ use std::cmp::Ordering;
 use std::fmt;
 #[cfg(feature = "use_std")]
 use std::hash::Hash;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 use std::fmt::Write;
-#[cfg(feature = "use_std")]
-type VecIntoIter<T> = ::std::vec::IntoIter<T>;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
+type VecIntoIter<T> = alloc::vec::IntoIter<T>;
+#[cfg(feature = "use_alloc")]
 use std::iter::FromIterator;
 
 #[macro_use]
@@ -100,38 +109,38 @@ pub mod structs {
     };
     #[allow(deprecated)]
     pub use crate::adaptors::{MapResults, Step};
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::adaptors::MultiProduct;
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::combinations::Combinations;
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::combinations_with_replacement::CombinationsWithReplacement;
     pub use crate::cons_tuples_impl::ConsTuples;
     pub use crate::exactly_one_err::ExactlyOneError;
     pub use crate::format::{Format, FormatWith};
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::groupbylazy::{IntoChunks, Chunk, Chunks, GroupBy, Group, Groups};
     pub use crate::intersperse::{Intersperse, IntersperseWith};
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::kmerge_impl::{KMerge, KMergeBy};
     pub use crate::merge_join::MergeJoinBy;
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::multipeek_impl::MultiPeek;
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::peek_nth::PeekNth;
     pub use crate::pad_tail::PadUsing;
     pub use crate::peeking_take_while::PeekingTakeWhile;
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::permutations::Permutations;
     pub use crate::process_results_impl::ProcessResults;
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::put_back_n_impl::PutBackN;
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::rciter_impl::RcIter;
     pub use crate::repeatn::RepeatN;
     #[allow(deprecated)]
     pub use crate::sources::{RepeatCall, Unfold, Iterate};
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     pub use crate::tee::Tee;
     pub use crate::tuple_impl::{TupleBuffer, TupleWindows, CircularTupleWindows, Tuples};
     #[cfg(feature = "use_std")]
@@ -153,7 +162,7 @@ pub use crate::concat_impl::concat;
 pub use crate::cons_tuples_impl::cons_tuples;
 pub use crate::diff::diff_with;
 pub use crate::diff::Diff;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 pub use crate::kmerge_impl::{kmerge_by};
 pub use crate::minmax::MinMaxResult;
 pub use crate::peeking_take_while::PeekingNext;
@@ -172,41 +181,41 @@ pub mod free;
 pub use crate::free::*;
 mod concat_impl;
 mod cons_tuples_impl;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod combinations;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod combinations_with_replacement;
 mod exactly_one_err;
 mod diff;
 mod format;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod group_map;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod groupbylazy;
 mod intersperse;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod kmerge_impl;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod lazy_buffer;
 mod merge_join;
 mod minmax;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod multipeek_impl;
 mod pad_tail;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod peek_nth;
 mod peeking_take_while;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod permutations;
 mod process_results_impl;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod put_back_n_impl;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod rciter_impl;
 mod repeatn;
 mod size_hint;
 mod sources;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 mod tee;
 mod tuple_impl;
 #[cfg(feature = "use_std")]
@@ -530,7 +539,7 @@ pub trait Itertools : Iterator {
     /// }
     /// assert_eq!(data_grouped, vec![(true, vec![1, 3]), (false, vec![-2, -2]), (true, vec![1, 0, 1, 2])]);
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn group_by<K, F>(self, key: F) -> GroupBy<K, Self, F>
         where Self: Sized,
               F: FnMut(&Self::Item) -> K,
@@ -566,7 +575,7 @@ pub trait Itertools : Iterator {
     ///     assert_eq!(4, chunk.sum());
     /// }
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn chunks(self, size: usize) -> IntoChunks<Self>
         where Self: Sized,
     {
@@ -704,7 +713,7 @@ pub trait Itertools : Iterator {
     /// itertools::assert_equal(t2, 0..4);
     /// itertools::assert_equal(t1, 1..4);
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn tee(self) -> (Tee<Self>, Tee<Self>)
         where Self: Sized,
               Self::Item: Clone
@@ -911,7 +920,7 @@ pub trait Itertools : Iterator {
     /// let it = vec![a, b, c].into_iter().kmerge();
     /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5]);
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn kmerge(self) -> KMerge<<Self::Item as IntoIterator>::IntoIter>
         where Self: Sized,
               Self::Item: IntoIterator,
@@ -940,7 +949,7 @@ pub trait Itertools : Iterator {
     /// assert_eq!(it.next(), Some(0.));
     /// assert_eq!(it.last(), Some(-7.));
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn kmerge_by<F>(self, first: F)
         -> KMergeBy<<Self::Item as IntoIterator>::IntoIter, F>
         where Self: Sized,
@@ -996,7 +1005,7 @@ pub trait Itertools : Iterator {
     /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 5]));
     /// assert_eq!(multi_prod.next(), None);
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn multi_cartesian_product(self) -> MultiProduct<<Self::Item as IntoIterator>::IntoIter>
         where Self: Iterator + Sized,
               Self::Item: IntoIterator,
@@ -1316,7 +1325,7 @@ pub trait Itertools : Iterator {
     ///     vec![2, 2],
     /// ]);
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn combinations(self, k: usize) -> Combinations<Self>
         where Self: Sized,
               Self::Item: Clone
@@ -1343,7 +1352,7 @@ pub trait Itertools : Iterator {
     ///     vec![3, 3],
     /// ]);
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn combinations_with_replacement(self, k: usize) -> CombinationsWithReplacement<Self>
     where
         Self: Sized,
@@ -1389,7 +1398,7 @@ pub trait Itertools : Iterator {
     ///
     /// Note: The source iterator is collected lazily, and will not be
     /// re-iterated if the permutations adaptor is completed and re-iterated.
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn permutations(self, k: usize) -> Permutations<Self>
         where Self: Sized,
               Self::Item: Clone
@@ -1681,7 +1690,7 @@ pub trait Itertools : Iterator {
 
     /// `.collect_vec()` is simply a type specialization of `.collect()`,
     /// for convenience.
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn collect_vec(self) -> Vec<Self::Item>
         where Self: Sized
     {
@@ -1708,7 +1717,7 @@ pub trait Itertools : Iterator {
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn try_collect<T, U, E>(self) -> Result<U, E>
     where
         Self: Sized + Iterator<Item = Result<T, E>>,
@@ -1758,7 +1767,7 @@ pub trait Itertools : Iterator {
     /// assert_eq!(["a", "b", "c"].iter().join(", "), "a, b, c");
     /// assert_eq!([1, 2, 3].iter().join(", "), "1, 2, 3");
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn join(&mut self, sep: &str) -> String
         where Self::Item: std::fmt::Display
     {
@@ -2189,7 +2198,7 @@ pub trait Itertools : Iterator {
     /// itertools::assert_equal(text.chars().sorted(),
     ///                         "abcdef".chars());
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn sorted(self) -> VecIntoIter<Self::Item>
         where Self: Sized,
               Self::Item: Ord
@@ -2224,7 +2233,7 @@ pub trait Itertools : Iterator {
     /// itertools::assert_equal(oldest_people_first,
     ///                         vec!["Jill", "Jack", "Jane", "John"]);
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn sorted_by<F>(self, cmp: F) -> VecIntoIter<Self::Item>
         where Self: Sized,
               F: FnMut(&Self::Item, &Self::Item) -> Ordering,
@@ -2257,7 +2266,7 @@ pub trait Itertools : Iterator {
     /// itertools::assert_equal(oldest_people_first,
     ///                         vec!["Jill", "Jack", "Jane", "John"]);
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn sorted_by_key<K, F>(self, f: F) -> VecIntoIter<Self::Item>
         where Self: Sized,
               K: Ord,
@@ -2800,7 +2809,7 @@ pub trait Itertools : Iterator {
     /// assert_eq!(iter.next(), Some(0));
     /// assert_eq!(iter.peek(), Some(&1));
     /// ```
-    #[cfg(feature = "use_std")]
+    #[cfg(feature = "use_alloc")]
     fn multipeek(self) -> MultiPeek<Self>
     where
         Self: Sized,
diff --git a/src/multipeek_impl.rs b/src/multipeek_impl.rs
index 16327eacc..986e5b405 100644
--- a/src/multipeek_impl.rs
+++ b/src/multipeek_impl.rs
@@ -1,5 +1,5 @@
 use std::iter::Fuse;
-use std::collections::VecDeque;
+use alloc::collections::VecDeque;
 use crate::size_hint;
 use crate::PeekingNext;
 
diff --git a/src/peek_nth.rs b/src/peek_nth.rs
index 83abac8b9..d22258b35 100644
--- a/src/peek_nth.rs
+++ b/src/peek_nth.rs
@@ -1,6 +1,6 @@
 use crate::size_hint;
 use crate::PeekingNext;
-use std::collections::VecDeque;
+use alloc::collections::VecDeque;
 use std::iter::Fuse;
 
 /// See [`peek_nth()`](../fn.peek_nth.html) for more information.
diff --git a/src/peeking_take_while.rs b/src/peeking_take_while.rs
index 5fadf76c5..70ef988f1 100644
--- a/src/peeking_take_while.rs
+++ b/src/peeking_take_while.rs
@@ -1,6 +1,6 @@
 use std::iter::Peekable;
 use crate::PutBack;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 use crate::PutBackN;
 
 /// An iterator that allows peeking at an element before deciding to accept it.
@@ -52,7 +52,7 @@ impl<I> PeekingNext for PutBack<I>
     }
 }
 
-#[cfg(feature = "use_std")]
+#[cfg(feature = "use_alloc")]
 impl<I> PeekingNext for PutBackN<I>
     where I: Iterator,
 {
@@ -137,10 +137,10 @@ peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> }
 peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> }
 peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> }
 peeking_next_by_clone! { [T] ::std::iter::Empty<T> }
-#[cfg(feature = "use_std")]
-peeking_next_by_clone! { ['a, T] ::std::collections::linked_list::Iter<'a, T> }
-#[cfg(feature = "use_std")]
-peeking_next_by_clone! { ['a, T] ::std::collections::vec_deque::Iter<'a, T> }
+#[cfg(feature = "use_alloc")]
+peeking_next_by_clone! { ['a, T] alloc::collections::linked_list::Iter<'a, T> }
+#[cfg(feature = "use_alloc")]
+peeking_next_by_clone! { ['a, T] alloc::collections::vec_deque::Iter<'a, T> }
 
 // cloning a Rev has no extra overhead; peekable and put backs are never DEI.
 peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator]
diff --git a/src/permutations.rs b/src/permutations.rs
index fb4dd5085..45126ffbd 100644
--- a/src/permutations.rs
+++ b/src/permutations.rs
@@ -1,3 +1,4 @@
+use alloc::vec::Vec;
 use std::fmt;
 use std::iter::once;
 
diff --git a/src/put_back_n_impl.rs b/src/put_back_n_impl.rs
index 21e733fe4..60ea8e649 100644
--- a/src/put_back_n_impl.rs
+++ b/src/put_back_n_impl.rs
@@ -1,3 +1,5 @@
+use alloc::vec::Vec;
+
 use crate::size_hint;
 
 /// An iterator adaptor that allows putting multiple
diff --git a/src/rciter_impl.rs b/src/rciter_impl.rs
index 9d044d3c5..9122dadc9 100644
--- a/src/rciter_impl.rs
+++ b/src/rciter_impl.rs
@@ -1,6 +1,6 @@
 
 use std::iter::IntoIterator;
-use std::rc::Rc;
+use alloc::rc::Rc;
 use std::cell::RefCell;
 
 /// A wrapper for `Rc<RefCell<I>>`, that implements the `Iterator` trait.
diff --git a/src/tee.rs b/src/tee.rs
index 18337b1e6..0b003027d 100644
--- a/src/tee.rs
+++ b/src/tee.rs
@@ -1,8 +1,8 @@
 use super::size_hint;
 
 use std::cell::RefCell;
-use std::collections::VecDeque;
-use std::rc::Rc;
+use alloc::collections::VecDeque;
+use alloc::rc::Rc;
 
 /// Common buffer object for the two tee halves
 #[derive(Debug)]


Test patch: