How do I pass a function pointer recursively? - iterator

I want to write an Iterator adaptor which applies a function recursively to its underlying Iterator. Recursively because the variant IR::Loop includes a Vec<IR>, of which an iterator should also be passed to the function.
The function should take an &mut Iterator<Item = IR> and use it to compute the next value of the iterator, (like itertools::batching).
use std::iter::Peekable;
#[derive(Clone)]
enum IR {
OperationA,
OperationB,
Loop(Vec<IR>),
}
pub trait MyItertools: Iterator {
fn apply_recursive<F: Fn(&mut Peekable<Self>) -> Option<Self::Item>>(
self,
f: F,
) -> ApplyRecursive<Self, F>
where
Self: Sized,
Self::Item: Clone,
{
ApplyRecursive {
iter: self.peekable(),
f: f,
}
}
}
impl<T: ?Sized> MyItertools for T
where
T: Iterator,
{
}
//applies a function recursively to some Iterator with Item=IR
#[derive(Clone)]
struct ApplyRecursive<I, F>
where
I: Iterator,
I::Item: Clone,
{
iter: Peekable<I>,
f: F,
}
impl<I: Iterator<Item = IR>, F> Iterator for ApplyRecursive<I, F>
where
F: Fn(&mut Peekable<I>)
-> Option<I::Item>,
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
match self.iter.peek() {
Some(&IR::Loop(code)) => {
self.iter.next(); //advance the iterator
let code: Vec<IR> = code.into_iter().apply_recursive(self.f).collect();
Some(IR::Loop(code))
}
Some(x) => (self.f)(&mut self.iter),
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
fn main() {}
playground
What am I doing wrong? I don't even understand the error message:
error[E0277]: the trait bound `for<'r> F: std::ops::Fn<(&'r mut std::iter::Peekable<std::vec::IntoIter<IR>>,)>` is not satisfied
--> src/main.rs:54:54
|
54 | let code: Vec<IR> = code.into_iter().apply_recursive(self.f).collect();
| ^^^^^^^^^^^^^^^ the trait `for<'r> std::ops::Fn<(&'r mut std::iter::Peekable<std::vec::IntoIter<IR>>,)>` is not implemented for `F`
|
= help: consider adding a `where for<'r> F: std::ops::Fn<(&'r mut std::iter::Peekable<std::vec::IntoIter<IR>>,)>` bound
error[E0277]: the trait bound `for<'r> F: std::ops::FnOnce<(&'r mut std::iter::Peekable<std::vec::IntoIter<IR>>,)>` is not satisfied
--> src/main.rs:54:54
|
54 | let code: Vec<IR> = code.into_iter().apply_recursive(self.f).collect();
| ^^^^^^^^^^^^^^^ the trait `for<'r> std::ops::FnOnce<(&'r mut std::iter::Peekable<std::vec::IntoIter<IR>>,)>` is not implemented for `F`
|
= help: consider adding a `where for<'r> F: std::ops::FnOnce<(&'r mut std::iter::Peekable<std::vec::IntoIter<IR>>,)>` bound
error: no method named `collect` found for type `ApplyRecursive<std::vec::IntoIter<IR>, F>` in the current scope
--> src/main.rs:54:78
|
54 | let code: Vec<IR> = code.into_iter().apply_recursive(self.f).collect();
| ^^^^^^^
|
= note: the method `collect` exists but the following trait bounds were not satisfied: `F : std::ops::Fn<(&mut std::iter::Peekable<std::vec::IntoIter<IR>>,)>`, `ApplyRecursive<std::vec::IntoIter<IR>, F> : std::iter::Iterator`
= help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `collect`, perhaps you need to implement it:
= help: candidate #1: `std::iter::Iterator`

The last error indicates that you don't have an Iterator. Iterator is only implemented for your struct under certain conditions, and you aren't meeting them. The second error explains why.
the trait for<'r> Fn<(&'r mut IntoIter<IR>,)> is not implemented for the type F
So, why does the compiler think this won't work? Let's look at your constraints:
impl<I, F> Iterator for ApplyRecursive<I, F>
where
I: Iterator<Item = IR>
F: Fn(&mut Peekable<I>) -> Option<I::Item>,
This structure refers to a concrete type I that implements Iterator. Then F is a concrete type that accepts a mutable reference to the same concrete type as I. However, you try to use your function (specialized for whatever type it happens to be) on the concrete type IntoIter - but this might be a different concrete type!
The easiest fix is to remove the generics here:
impl<F> Iterator for ApplyRecursive<vec::IntoIter<IR>, F>
where
F: Fn(&mut vec::IntoIter<IR>) -> Option<IR>,
{
type Item = IR;
fn next(&mut self) -> Option<IR> {
This unlocks a whole other slew of errors about mutability, accessing private fields, and exporting private types, but I think it gets over this hump.
Alternatively, we can change F to accept a trait object, and not worry about specializing it:
pub trait CustomIter: Iterator {
fn apply_recursive<F>(self, f: F) -> ApplyRecursive<Self, F>
where
F: Fn(&mut Iterator<Item = Self::Item>) -> Option<Self::Item>,
Self: Sized,
Self::Item: Clone,
{
ApplyRecursive { iter: self.peekable(), f: f }
}
}
impl<I, F> Iterator for ApplyRecursive<I, F>
where
I: Iterator<Item = IR>,
F: Fn(&mut Iterator<Item = IR>) -> Option<IR>,
{
type Item = I::Item;
fn next(&mut self) -> Option<IR> {

Related

Type mismatch resolving iterator Item to a pointer with an explicit lifetime

I'm trying to add functions to Iterator where the associated type Item is a reference to a struct with an explicit lifetime.
When I've wanted to modify the iterator state or return a new value I've had no problems, but when I attempt to return a new Iterator where Item is a reference with an explicit lifetime, the compiler complains.
Example
use std::marker::PhantomData;
/// First, an "Inner" struct to be contained in my custom iterator
pub struct Inner {
text: String,
}
/// Then, the "CustomIterator" in question. Notice that `Item` is `&'a Inner`.
pub struct CustomIterator<'a, I: Iterator<Item = &'a Inner>> {
iter: I,
_marker: PhantomData<&'a i8>,
}
/// Implementing Iterator for CustomIterator so as to define the `next()` function, as you do...
impl<'a, I: Iterator<Item = &'a Inner>> Iterator for CustomIterator<'a, I> {
type Item = &'a Inner;
fn next(&mut self) -> Option<Self::Item> {
println!("Custom next called");
self.iter.next()
}
}
/// Now, creating a custom trait definition called IterateMore that:
/// 1. inherits Iterator
/// 2. includes a default method called `more` which returns a `CustomIterator`
pub trait IterateMore<'a>: Iterator {
type Item;
fn more(self) -> CustomIterator<'a, Self>
where
Self: Sized;
}
/// Implementing `IterateMore` for an iterator of the specific type `Iterator<Item=&'a Inner>`
impl<'a, I: Iterator<Item = &'a Inner>> IterateMore<'a> for I
where
I: Iterator,
{
type Item = &'a Inner;
fn more(self) -> CustomIterator<'a, Self>
where
Self: Sized,
{
CustomIterator {
iter: self,
_marker: PhantomData,
}
}
}
fn main() {
let inner = Inner {
text: "Hello world".to_string(),
};
let inners = vec![&inner];
inners.iter().more().next();
}
(See it on repl.it)
Error
error[E0271]: type mismatch resolving `<Self as std::iter::Iterator>::Item == &'a Inner`
--> src/main.rs:28:5
|
28 | / fn more(self) -> CustomIterator<'a, Self>
29 | | where
30 | | Self: Sized;
| |____________________^ expected associated type, found reference
|
= note: expected type `<Self as std::iter::Iterator>::Item`
found type `&'a Inner`
= note: required by `CustomIterator`
Why is Item not being resolved here? It is a bit frustrating as the compiler also complains if I try to set &'a Inner as the default Item type in the trait definition, saying:
error: associated type defaults are unstable (see issue #29661)
How could this be fixed or done differently?
It is unclear to me why you'd want to restrict the wrapped iterator to some custom type (given that you still have to write down the restriction every time you use the type, although that might change). But perhaps your "real" next function does something funny.
PhantomData doesn't seem to be necessary (anymore) to "use" the lifetime when it is used in a where-clause.
IterateMore shouldn't have an Item associated type, given Iterator already has it. (If you'd really need a new type pick a different name)
As IterateMore uses the CustomIterator type it needs to repeat the requirements, in this case Iterator<Item = &'a Inner> (that is what the type mismatch error is about); this is not the same as saying type Item = &'a Inner in the trait definition.
Playground
/// an "Inner" struct to be contained in my custom iterator
pub struct Inner {
text: String,
}
pub struct CustomIterator<'a, I>
where
I: Iterator<Item = &'a Inner>,
{
iter: I,
}
impl<'a, I> Iterator for CustomIterator<'a, I>
where
I: Iterator<Item = &'a Inner>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
println!("Custom next called");
self.iter.next()
}
}
pub trait IterateMore<'a>: Iterator<Item = &'a Inner> + Sized {
fn more(self) -> CustomIterator<'a, Self>;
}
impl<'a, I> IterateMore<'a> for I
where
I: Iterator<Item = &'a Inner>,
{
fn more(self) -> CustomIterator<'a, Self> {
CustomIterator { iter: self }
}
}
fn main() {
let inner = Inner {
text: "Hello world".to_string(),
};
let inners = vec![inner];
inners.iter().more().next();
}
You could also remove the type restrictions everywhere like this (and only add it back in the place you actually need/want it):
Playground
pub struct CustomIterator<I> {
iter: I,
}
impl<I> Iterator for CustomIterator<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
println!("Custom next called");
self.iter.next()
}
}
pub trait IterateMore: Iterator + Sized {
fn more(self) -> CustomIterator<Self>;
}
impl<I> IterateMore for I
where
I: Iterator,
{
fn more(self) -> CustomIterator<Self>
{
CustomIterator { iter: self }
}
}
fn main() {
let inners = vec!["Hello world".to_string()];
inners.iter().more().next();
}

How can we write a generic function for checking Serde serialization and deserialization?

In a project where custom Serde (1.0) serialization and deserialization methods are involved, I have relied on this test routine to check whether serializing an object and back would yield an equivalent object.
// let o: T = ...;
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, o2);
Doing this inline works pretty well. My next step towards reusability was to make a function check_serde for this purpose.
pub fn check_serde<T>(o: T)
where
T: Debug + PartialEq<T> + Serialize + DeserializeOwned,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, o2);
}
This works well for owning types, but not for types with lifetime bounds (Playground):
check_serde(5);
check_serde(vec![1, 2, 5]);
check_serde("five".to_string());
check_serde("wait"); // [E0279]
The error:
error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`)
--> src/main.rs:24:5
|
24 | check_serde("wait"); // [E0277]
| ^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `&str`
= note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `&str`
= note: required by `check_serde`
As I wish to make the function work with these cases (including structs with string slices), I attempted a new version with an explicit object deserialization lifetime:
pub fn check_serde<'a, T>(o: &'a T)
where
T: Debug + PartialEq<T> + Serialize + Deserialize<'a>,
{
let buf: Vec<u8> = to_vec(o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, &o2);
}
check_serde(&5);
check_serde(&vec![1, 2, 5]);
check_serde(&"five".to_string());
check_serde(&"wait"); // [E0405]
This implementation leads to another issue, and it won't compile (Playground).
error[E0597]: `buf` does not live long enough
--> src/main.rs:14:29
|
14 | let o2: T = from_slice(&buf).unwrap();
| ^^^ does not live long enough
15 | assert_eq!(o, &o2);
16 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 10:1...
--> src/main.rs:10:1
|
10 | / pub fn check_serde<'a, T>(o: &'a T)
11 | | where T: Debug + PartialEq<T> + Serialize + Deserialize<'a>
12 | | {
13 | | let buf: Vec<u8> = to_vec(o).unwrap();
14 | | let o2: T = from_slice(&buf).unwrap();
15 | | assert_eq!(o, &o2);
16 | | }
| |_^
I have already expected this one: this version implies that the serialized content (and so the deserialized object) lives as long as the input object, which is not true. The buffer is only meant to live as long as the function's scope.
My third attempt seeks to build owned versions of the original input, thus evading the issue of having a deserialized object with different lifetime boundaries. The ToOwned trait appears to suit this use case.
pub fn check_serde<'a, T: ?Sized>(o: &'a T)
where
T: Debug + ToOwned + PartialEq<<T as ToOwned>::Owned> + Serialize,
<T as ToOwned>::Owned: Debug + DeserializeOwned,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T::Owned = from_slice(&buf).unwrap();
assert_eq!(o, &o2);
}
This makes the function work for plain string slices now, but not for composite objects containing them (Playground):
check_serde(&5);
check_serde(&vec![1, 2, 5]);
check_serde(&"five".to_string());
check_serde("wait");
check_serde(&("There's more!", 36)); // [E0279]
Again, we stumble upon the same error kind as the first version:
error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`)
--> src/main.rs:25:5
|
25 | check_serde(&("There's more!", 36)); // [E0279]
| ^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `&str`
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `(&str, {integer})`
= note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `(&str, {integer})`
= note: required by `check_serde`
Granted, I'm at a loss. How can we build a generic function that, using Serde, serializes an object and deserializes it back into a new object? In particular, can this function be made in Rust (stable or nightly), and if so, what adjustments to my implementation are missing?
Unfortunately, what you need is a feature that is not yet implemented in Rust: generic associated types.
Let's look at a different variant of check_serde:
pub fn check_serde<T>(o: T)
where
for<'a> T: Debug + PartialEq<T> + Serialize + Deserialize<'a>,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, o2);
}
fn main() {
check_serde("wait"); // [E0279]
}
The problem here is that o2 cannot be of type T: o2 refers to buf, which is a local variable, but type parameters cannot be inferred to types constrained by a lifetime that is restricted to the function's body. We'd like for T to be something like &str without a specific lifetime attached to it.
With generic associated types, this could be solved with something like this (obviously I can't test it, since it's not implemented yet):
trait SerdeFamily {
type Member<'a>: Debug + for<'b> PartialEq<Self::Member<'b>> + Serialize + Deserialize<'a>;
}
struct I32Family;
struct StrFamily;
impl SerdeFamily for I32Family {
type Member<'a> = i32; // ignoring a parameter is allowed
}
impl SerdeFamily for StrFamily {
type Member<'a> = &'a str;
}
pub fn check_serde<'a, Family>(o: Family::Member<'a>)
where
Family: SerdeFamily,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
// `o2` is of type `Family::Member<'b>`
// with a lifetime 'b different from 'a
let o2: Family::Member = from_slice(&buf).unwrap();
assert_eq!(o, o2);
}
fn main() {
check_serde::<I32Family>(5);
check_serde::<StrFamily>("wait");
}
The answer from Francis Gagné has shown that we cannot do this efficiently without generic associated types. Establishing deep ownership of the deserialized object is a possible work-around which I describe here.
The third attempt is very close to a flexible solution, but it falls short due to how std::borrow::ToOwned works. The trait is not suitable for retrieving a deeply owned version of an object. Attempting to use the implementation of ToOwned for &str, for instance, gives you another string slice.
let a: &str = "hello";
let b: String = (&a).to_owned(); // expected String, got &str
Likewise, the Owned type for a struct containing string slices cannot be a struct containing Strings. In code:
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Foo<'a>(&str, i32);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FooOwned(String, i32);
We cannot impl ToOwned for Foo to provide FooOwned because:
If we derive Clone, the implementation of ToOwned for T: Clone is only applicable to Owned = Self.
Even with a custom implementation of ToOwned, the trait requires that the owned type can be borrowed into the original type (due to the constraint Owned: Borrow<Self>). That is, we are supposed to be able to retrieve a &Foo(&str, i32) out of a FooOwned, but their internal structure is different, and so this is not attainable.
This means that, in order to follow the third approach, we need a different trait. Let's have a new trait ToDeeplyOwned which turns an object into a fully owned one, with no slices or references involved.
pub trait ToDeeplyOwned {
type Owned;
fn to_deeply_owned(&self) -> Self::Owned;
}
The intent here is to produce a deep copy out of anything. There doesn't seem to be an easy catch-all implementation, but some tricks are possible. First, we can implement it to all reference types where T: ToDeeplyOwned.
impl<'a, T: ?Sized + ToDeeplyOwned> ToDeeplyOwned for &'a T {
type Owned = T::Owned;
fn to_deeply_owned(&self) -> Self::Owned {
(**self).to_deeply_owned()
}
}
At this point we would have to selectively implement it to non-reference types where we know it's ok. I wrote a macro for making this process less verbose, which uses to_owned() internally.
macro_rules! impl_deeply_owned {
($t: ty, $t2: ty) => { // turn $t into $t2
impl ToDeeplyOwned for $t {
type Owned = $t2;
fn to_deeply_owned(&self) -> Self::Owned {
self.to_owned()
}
}
};
($t: ty) => { // turn $t into itself, self-contained type
impl ToDeeplyOwned for $t {
type Owned = $t;
fn to_deeply_owned(&self) -> Self::Owned {
self.to_owned()
}
}
};
}
For the examples in the question to work, we need at least these:
impl_deeply_owned!(i32);
impl_deeply_owned!(String);
impl_deeply_owned!(Vec<i32>);
impl_deeply_owned!(str, String);
Once we implement the necessary traits on Foo/FooOwned and adapt serde_check to use the new trait, the code now compiles and runs successfully (Playground):
#[derive(Debug, PartialEq, Serialize)]
struct Foo<'a>(&'a str, i32);
#[derive(Debug, PartialEq, Clone, Deserialize)]
struct FooOwned(String, i32);
impl<'a> ToDeeplyOwned for Foo<'a> {
type Owned = FooOwned;
fn to_deeply_owned(&self) -> FooOwned {
FooOwned(self.0.to_string(), self.1)
}
}
impl<'a> PartialEq<FooOwned> for Foo<'a> {
fn eq(&self, o: &FooOwned) -> bool {
self.0 == o.0 && self.1 == o.1
}
}
pub fn check_serde<'a, T: ?Sized>(o: &'a T)
where
T: Debug + ToDeeplyOwned + PartialEq<<T as ToDeeplyOwned>::Owned> + Serialize,
<T as ToDeeplyOwned>::Owned: Debug + DeserializeOwned,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T::Owned = from_slice(&buf).unwrap();
assert_eq!(o, &o2);
}
// all of these are ok
check_serde(&5);
check_serde(&vec![1, 2, 5]);
check_serde(&"five".to_string());
check_serde("wait");
check_serde(&"wait");
check_serde(&Foo("There's more!", 36));
Update (04.09.2021):
The latest nightly has some fixes around GATs which basically allows the original example:
#![feature(generic_associated_types)]
use serde::{Deserialize, Serialize};
use serde_json::{from_slice, to_vec};
use std::fmt::Debug;
trait SerdeFamily {
type Member<'a>:
Debug +
for<'b> PartialEq<Self::Member<'b>> +
Serialize +
Deserialize<'a>;
}
struct I32Family;
struct StrFamily;
impl SerdeFamily for I32Family {
type Member<'a> = i32;
}
impl SerdeFamily for StrFamily {
type Member<'a> = &'a str;
}
fn check_serde<F: SerdeFamily>(o: F::Member<'_>) {
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: F::Member<'_> = from_slice(&buf).unwrap();
assert_eq!(o, o2);
}
fn main() {
check_serde::<I32Family>(5);
check_serde::<StrFamily>("wait");
}
The example above compiles now: playground.
As of now it's possible to implement this on rust nightly (with an explicit variance workaround):
#![feature(generic_associated_types)]
use serde::{Deserialize, Serialize};
use serde_json::{from_slice, to_vec};
use std::fmt::Debug;
trait SerdeFamily {
type Member<'a>: Debug + PartialEq + Serialize + Deserialize<'a>;
// https://internals.rust-lang.org/t/variance-of-lifetime-arguments-in-gats/14769/19
fn upcast_gat<'short, 'long: 'short>(long: Self::Member<'long>) -> Self::Member<'short>;
}
struct I32Family;
struct StrFamily;
impl SerdeFamily for I32Family {
type Member<'a> = i32; // we can ignore parameters
fn upcast_gat<'short, 'long: 'short>(long: Self::Member<'long>) -> Self::Member<'short> {
long
}
}
impl SerdeFamily for StrFamily {
type Member<'a> = &'a str;
fn upcast_gat<'short, 'long: 'short>(long: Self::Member<'long>) -> Self::Member<'short> {
long
}
}
fn check_serde<F: SerdeFamily>(o: F::Member<'_>) {
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: F::Member<'_> = from_slice(&buf).unwrap();
assert_eq!(F::upcast_gat(o), o2);
}
fn main() {
check_serde::<I32Family>(5);
check_serde::<StrFamily>("wait");
}
Playground
Simple (but a little awkward) solution: Provide buf from outside of the function.
pub fn check_serde<'a, T>(o: &'a T, buf: &'a mut Vec<u8>)
where
T: Debug + PartialEq<T> + Serialize + Deserialize<'a>,
{
*buf = to_vec(o).unwrap();
let o2: T = from_slice(buf).unwrap();
assert_eq!(o, &o2);
}
buf can be reused with Cursor
pub fn check_serde_with_cursor<'a, T>(o: &'a T, buf: &'a mut Vec<u8>)
where
T: Debug + PartialEq<T> + Serialize + Deserialize<'a>,
{
buf.clear();
let mut cursor = Cursor::new(buf);
to_writer(&mut cursor, o).unwrap();
let o2: T = from_slice(cursor.into_inner()).unwrap();
assert_eq!(o, &o2);
}

Iterator returning a reference to itself

I'm aware of Lifetime in Iterator impl, but I'd like some more detail to help me properly understand.
I want to write an infinite Iterator that returns &[0], &[0, 1], &[0, 1, 2], etc... . I'd like to write this:
struct Countings(Vec<usize>);
impl Countings {
fn new() -> Countings { Countings(vec![]) }
}
impl Iterator for Countings {
type Item = &[usize];
fn next(&mut self) -> Option<Self::Item> {
self.0.push(self.0.len());
Some(self.0.as_slice())
}
}
I can't because the type Countings::Item does not have a lifetime.
error[E0106]: missing lifetime specifier
--> src/lib.rs:8:17
|
8 | type Item = &[usize];
| ^ expected lifetime parameter
So I add one. It has to be bound by the impl Iterator. That, in turn, requires a lifetime parameter on struct Countings. So far, I'm here:
struct Countings<'a>(Vec<usize>);
impl<'a> Countings<'a> {
fn new() -> Countings<'a> { Countings(vec![]) }
}
impl<'a> Iterator for Countings<'a> {
type Item = &'a [usize];
fn next(&mut self) -> Option<Self::Item> {
self.0.push(self.0.len());
Some(self.0.as_slice())
}
}
Now I have a different error:
error[E0392]: parameter `'a` is never used
--> src/lib.rs:1:18
|
1 | struct Countings<'a>(Vec<usize>);
| ^^
|
= help: consider removing `'a` or using a marker such as `std::marker::PhantomData`
I seriously consider it:
use std::marker::PhantomData;
struct Countings<'a>(Vec<usize>, PhantomData<&'a [usize]>);
impl<'a> Countings<'a> {
fn new() -> Countings<'a> { Countings(vec![], PhantomData) }
}
impl<'a> Iterator for Countings<'a> {
type Item = &'a [usize];
fn next(&mut self) -> Option<Self::Item> {
self.0.push(self.0.len());
Some(self.0.as_slice())
}
}
but to no avail:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:14:25
|
14 | Some(self.0.as_slice())
| ^^^^^^^^
Question 1: What are the "conflicting requirements"?
Question 2: The answer cited above says that Item must borrow from something that the Iterator wraps. I have read the source for std::slice::Windows which is a good example. However, in my case I want to mutate the Vec each time next() is called. Is that possible?
Question 1: What are the "conflicting requirements"?
The borrow you try to return does not have lifetime 'a, as promised. Rather, it has the same lifetime as self. If the signature for next was written in full, it would be:
fn next<'b>(&'b mut self) -> Option<&'a [usize]>
Returning an Option<&'b [usize]> (with lifetime 'b instead of 'a) would be valid if it weren't for the fact that it violates the contract for the Iterator trait. However, it would freeze self until the result is dropped; i.e. you could not call next twice and use the result of both calls together. That's because each call to next can potentially invalidate the previously returned slices; pushing to a Vec can relocate the storage in memory to make room for additional elements, so the pointers in the slices would no longer be valid.
Question 2: The answer cited above says that Item must borrow from something that the Iterator wraps. I have read the source for std::slice::Windows which is a good example. However, in my case I want to mutate the Vec each time next() is called. Is that possible?
It's not possible to do this with the Iterator trait, so you won't be able to use a for loop on your struct. However, you can do it (with the caveat mentioned above) with an ordinary method.
struct Countings(Vec<usize>);
impl Countings {
fn new() -> Countings { Countings(vec![]) }
fn next<'a>(&'a mut self) -> &'a [usize] {
let item = self.0.len();
self.0.push(item);
self.0.as_slice()
}
}
As Francis mentioned, it is not possible to modify the underlying vector during iteration. However, if you were to somehow have the possibility to specify the iteration bound, then things would be much easier:
You would create the vector [0, 1, 2, ...]
And then create an iterator that returns an ever-growing slice, up to the length of the vector
Just the iterator:
struct EverGrowingIterator<'a, T: 'a> {
slice: &'a [T],
current: usize,
}
impl<'a, T> Iterator for EverGrowingIterator<'a, T> {
type Item = &'a [T];
fn next(&mut self) -> Option<&'a [T]> {
if self.current >= self.slice.len() {
None
} else {
self.current += 1;
Some(&self.slice[0..self.current])
}
}
}
And then:
fn ever_growing<'a, T>(slice: &'a [T]) -> EverGrowingIterator<'a, T> {
EverGrowingIterator { slice: slice, current: 0 }
}
fn main() {
let v = vec![0, 1, 2];
for s in ever_growing(&v) {
println!("{:?}", s);
}
}
Will print:
[0]
[0, 1]
[0, 1, 2]
If you need to adapt this for infinite growth, you need to look into creating a custom container (not a Vec) that will grow while preserving references to previous slices. Something like a RefCell<Vec<Box<[T]>>> could be used.

How can I automatically implement FromIterator?

I have written a trait that specifies some methods similar to those of Vec:
pub trait Buffer {
type Item;
fn with_capacity(c: usize) -> Self;
fn push(&mut self, item: Self::Item);
}
I would like to implement FromIterator for all types that implement Buffer, as follows:
impl<T> iter::FromIterator<T::Item> for T
where T: Buffer
{
fn from_iter<I>(iter: I) -> Self
where I: IntoIterator<Item = T>
{
let mut iter = iter.into_iter();
let (lower, _) = iter.size_hint();
let ans = Self::with_capacity(lower);
while let Some(x) = iter.next() {
ans.push(x);
}
ans
}
}
The compiler won't let me:
error[E0210]: type parameter `T` must be used as the type parameter
for some local type (e.g. `MyStruct<T>`); only traits defined in the
current crate can be implemented for a type parameter
I think I understand the error message; it is preventing me from writing code that is incompatible with possible future changes to the standard library.
The only way around this error appears to be to implement FromIterator separately for every type for which I implement Buffer. This will involve copying out exactly the same code many times. Is there a a way to share the same implementation between all Buffer types?
You can't implement a trait from another crate for an arbitrary type, only for a type from your crate. However, you can move the implementation to a function and reduce amount of duplicated code:
fn buffer_from_iter<I, B>(iter: I) -> B
where I: IntoIterator<Item = B::Item>,
B: Buffer
{
let mut iter = iter.into_iter();
let (lower, _) = iter.size_hint();
let mut ans = B::with_capacity(lower);
while let Some(x) = iter.next() {
ans.push(x);
}
ans
}
struct S1;
impl Buffer for S1 {
type Item = i32;
fn with_capacity(c: usize) -> Self { unimplemented!() }
fn push(&mut self, item: Self::Item) { unimplemented!() }
}
impl std::iter::FromIterator<<S1 as Buffer>::Item> for S1 {
fn from_iter<I>(iter: I) -> Self
where I: IntoIterator<Item = <S1 as Buffer>::Item>
{
buffer_from_iter(iter)
}
}
This implementation of FromIterator can be wrapped into a macro to further reduce code duplication.

How can I add new methods to Iterator?

I want to define a .unique() method on iterators that enables me to iterate without duplicates.
use std::collections::HashSet;
struct UniqueState<'a> {
seen: HashSet<String>,
underlying: &'a mut Iterator<Item = String>,
}
trait Unique {
fn unique(&mut self) -> UniqueState;
}
impl Unique for Iterator<Item = String> {
fn unique(&mut self) -> UniqueState {
UniqueState {
seen: HashSet::new(),
underlying: self,
}
}
}
impl<'a> Iterator for UniqueState<'a> {
type Item = String;
fn next(&mut self) -> Option<String> {
while let Some(x) = self.underlying.next() {
if !self.seen.contains(&x) {
self.seen.insert(x.clone());
return Some(x);
}
}
None
}
}
This compiles. However, when I try to use in the same file:
fn main() {
let foo = vec!["a", "b", "a", "cc", "cc", "d"];
for s in foo.iter().unique() {
println!("{}", s);
}
}
I get the following error:
error[E0599]: no method named `unique` found for type `std::slice::Iter<'_, &str>` in the current scope
--> src/main.rs:37:25
|
37 | for s in foo.iter().unique() {
| ^^^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `unique`, perhaps you need to implement it:
candidate #1: `Unique`
What am I doing wrong? How would I extend this arbitrary hashable types?
In your particular case, it's because you have implemented your trait for an iterator of String, but your vector is providing an iterator of &str. Here's a more generic version:
use std::collections::HashSet;
use std::hash::Hash;
struct Unique<I>
where
I: Iterator,
{
seen: HashSet<I::Item>,
underlying: I,
}
impl<I> Iterator for Unique<I>
where
I: Iterator,
I::Item: Hash + Eq + Clone,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
while let Some(x) = self.underlying.next() {
if !self.seen.contains(&x) {
self.seen.insert(x.clone());
return Some(x);
}
}
None
}
}
trait UniqueExt: Iterator {
fn unique(self) -> Unique<Self>
where
Self::Item: Hash + Eq + Clone,
Self: Sized,
{
Unique {
seen: HashSet::new(),
underlying: self,
}
}
}
impl<I: Iterator> UniqueExt for I {}
fn main() {
let foo = vec!["a", "b", "a", "cc", "cc", "d"];
for s in foo.iter().unique() {
println!("{}", s);
}
}
Broadly, we create a new extension trait called UniqueExt which has Iterator as a supertrait. When Iterator is a supertrait, we will have access to the associated type Iterator::Item.
This trait defines the unique method, which is only valid to call when then iterated item can be:
Hashed
Compared for total equality
Cloned
Additionally, it requires that the item implementing Iterator have a known size at compile time. This is done so that the iterator can be consumed by the Unique iterator adapter.
The other important part is the blanket implementation of the trait for any type that also implements Iterator:
impl<I: Iterator> UniqueExt for I {}