Reputation: 197
I'm trying to define a trait with an associated type. I also want the associated type to implement Iterator
with its Item
associated type implementing AsRef<str>
.
While I know how to do it for a function or for a concrete Iterator::Item
type, I can't come up with a clear and concise solution for the original case.
Thanks to the helpful error messages, my compiling solution is:
trait Note
where
<<Self as Note>::FieldsIter as Iterator>::Item: AsRef<str>,
{
type FieldsIter: Iterator;
//other fields and methods omitted
}
The ugly where
clause makes me think that there should be a better way.
This doesn't compile since Item: AsRef<str>
is an illegal construction:
trait Note {
type FieldsIter: Iterator<Item: AsRef<str>>;
//other fields and methods omitted
}
This fails since impl
is not allowed here:
trait Note {
type FieldsIter: Iterator<Item = impl AsRef<str>>;
//other fields and methods omitted
}
This doesn't compile since I want Iterator::Item
to implement a certain trait, not to be a concrete type.
trait Note {
type FieldsIter: Iterator<Item = AsRef<str>>;
//other fields and methods omitted
}
Upvotes: 6
Views: 2757
Reputation: 430671
You can make one small improvement, but otherwise the current syntax for this is as you have discovered:
trait Note
where
<Self::FieldsIter as Iterator>::Item: AsRef<str>,
{
type FieldsIter: Iterator;
}
This is the disambiguated syntax, the only problem is there isn't yet a way to make the ambiguous version! Rust issue #38078 is open to allow the Foo::Bar::Baz
syntax.
RFC 2289 is also open as a way to improve this. With the RFC implemented, your second example should work:
trait Note {
type FieldsIter: Iterator<Item: AsRef<str>>;
}
One way you can work around this now is similar to IntoIterator
. This introduces another associated type:
trait Note {
type FieldsIter: Iterator<Item = Self::Item>;
type Item: AsRef<str>;
}
I'm not a fan of this because it introduces types that at first look to be orthogonal to each other, but in the end are tightly related.
Upvotes: 7