I'm trying to create a trait which includes functions that return an iterator over some internal data, which can then be implemented by different structs. A minimal example is as follows:
trait WrapperTrait {
type WrapperIterator: Iterator<Item=u32>;
fn iter(&self) -> Self::WrapperIterator;
}
struct Wrapper {
data: Vec<u32>
}
impl WrapperTrait for Wrapper {
type WrapperIterator = ...;
fn iter(&self) -> Self::WrapperIterator {
return self.data.iter().map(|&x| x);
}
}
However, the type for WrapperIterator
is rather complex - from an error message (created via type mismatch) I find it to be:
std::iter::Map<std::slice::Iter<'_, u32>, [[email protected]:45:37: 45:43]>
Is there a way to let Rust infer the correct type for WrapperIterator
?
Unfortunately, this is not yet possible in stable rust, but there is a plan to introduce this feature. If you want to try the (currently unstable) feature, you can do so on rust nightly with #![feature(min_type_alias_impl_trait)]
. You will have to add a type parameter to your trait :
#![feature(min_type_alias_impl_trait)]
trait WrapperTrait<'a> {
type WrapperIterator: Iterator<Item = u32> + 'a;
fn iter(&'a self) -> Self::WrapperIterator;
}
struct Wrapper {
data: Vec<u32>,
}
impl<'a> WrapperTrait<'a> for Wrapper {
type WrapperIterator = impl Iterator<Item = u32> + 'a;
fn iter(&'a self) -> Self::WrapperIterator {
self.data.iter().map(|&x| x)
}
}
playground link: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=a9434bcd32ea9c910fd0f9e329d17bd5
To do it without adding a lifetime parameter to the trait, one needs yet another unstable rust feature: Generic Associated Types.
#![feature(min_type_alias_impl_trait)]
#![feature(generic_associated_types)]
trait WrapperTrait {
type WrapperIterator<'a>: Iterator<Item = u32>;
fn iter<'a>(&'a self) -> Self::WrapperIterator<'a>;
}
struct Wrapper {
data: Vec<u32>,
}
impl WrapperTrait for Wrapper {
type WrapperIterator<'a> = impl Iterator<Item = u32>;
fn iter<'a>(&'a self) -> Self::WrapperIterator<'a>{
self.data.iter().map(|&x| x)
}
}
playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=049c875b27a0e9e472d854e6218df267
Is there a way to let Rust derive the correct type for
WrapperIterator
?
No. In fact, this is directly the opposite of what Rust does. You annotate function argument and return types, then the compiler can infer the types inside the method based on that.
Inferring top-level types from the body of the method leads to terrible error messages that occur far away from the location that caused them. Haskell learned this the hard way, and now advocates that all top-level functions have explicit type signatures. Rust chose to never go down that path. See also this answer; while it talks about lifetimes, many of the same points hold.
Your unasked question (how do I return this iterator) already has many duplicates:
Thank you for not asking yet another exact duplicate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With