[ TL;DR: the question requires quite a bit of context, the actual question is way below. ]
I have a type, its details are not important, for example:
struct Attribute { k : String, v : String }
Various structures in the program have a list of Attribute
s in them, some in simple Vec
, some in more complex data structures. I want to be able to list them. Since I want to abstract over different types of structures, that means a trait, and since I want to iterate, that means returning an iterator.
Morally, that would be:
trait With_attributes {
fn attributes(&self) -> Iterator <Item = &Attribute>;
}
Of course, it is not that simple: Iterator
is a trait too, the trait must be abstracted over the actual type of the iterator. Furthermore, iterators are usually borrowed, so a lifetime parameter is necessary:
trait With_attributes <'a, I : Iterator <Item = &'a Attribute>> {
fn attributes(&'a self) -> I;
}
Now, let us implement a simple structure with attributes:
struct Simple { attr : Vec <Attribute> }
Since the attributes are stored in a Vec
, the iterator will be std::slice::Iter
:
use std::slice::Iter;
impl <'a> With_attributes <'a, Iter <'a, Attribute>> for Simple {
fn attributes(&self) -> Iter <Attribute> {
return self.attr.iter();
}
}
I can now use the attributes()
function, for example:
fn dump_attributes(s : &Simple) {
for i in s.attributes() {
print!("{} -> {}\n", i.k, i.v);
}
}
The question: This works, but it is monomorphic, not using the trait abstraction. I change it to use the trait abstraction:
fn dump_attributes <I> (s : &With_attributes <I> ) {
And… it does not work:
19:5: 21:6 error: the trait `core::iter::Iterator` is not implemented for the type `I` [E0277]
19 for i in s.attributes() {
20 print!("{} -> {}\n", i.k, i.v);
21 }
19:5: 21:6 note: expansion site
19:5: 21:6 help: run `rustc --explain E0277` to see a detailed explanation
19:5: 21:6 note: `I` is not an iterator; maybe try calling `.iter()` or a similar method
Nuf? The definition of With_attributes
requires that I
is an iterator, why does the compiler not see it? If I add all the type annotations:
fn dump_attributes <'a, I> (s : &'a With_attributes <'a, I>)
where I : Iterator <Item = &'a Attribute> {
… it works. But why is it not implied by using the With_attributes
trait?
By the way, if there are simpler ways of doing any of the above, please let me know.