Trait method not found,

I'm trying to implement a trait for iterators without creating an own iterator:

fn main() {
   let mut v = vec![1,2,3];
   v = v.into_iter().scale(5).collect();
   println!("{:?}",v);
}

trait Scale<T: std::ops::Mul>: Iterator<Item = T> + Sized {
    fn scale(self, factor: T) -> Map<Self,dyn Fn(T)<Output = T>> {
        self.map(|x: T| x * factor)
    }
}

impl<T: std::ops::Mul, I: Iterator<Item = T>> Scale<T> for I {}

However, the compiler tell me that scale() isn't found in IntoIter, even IntoIterimplements Iterator. Where is my misconception?

That code was a little jumbled and I can't answer your question or explain the details of this. But I was able to follow the suggestions of the compiler errors (which you didn't post, BTW) and eventually got it to compile and run:

trait Scale<T: Copy + std::ops::Mul<Output = T> + 'static>:
    Iterator<Item = T>
where
    Self: Sized,
{
    fn scale(self, factor: T) -> impl Iterator<Item = T> {
        self.map(move |x: T| x * factor)
    }
}

impl<
        T: Copy + std::ops::Mul<Output = T> + 'static,
        I: Iterator<Item = T>,
    > Scale<T> for I
{
}

If it were me, I would probably just use a free function to make this simpler:

fn scale<I, T>(iter: I, factor: T) -> impl Iterator<Item = T>
where
    I: Iterator<Item = T>,
    T: Copy + std::ops::Mul<Output = T>,
{
    iter.map(move |x: T| x * factor)
}

In the code you posted, the compiler suggested specific changes. It doesn't always do this, but when it does it is worth trying them or at least thinking about them.

Do you read the compiler errors in your IDE, or on the command line when running cargo? I ask because some IDEs don't show the full error, so you'll miss the suggestions. If you're using vscode, be sure to click the link that says Click for full compiler diagnostic and you'll see the same thing that you would in the terminal.

1 Like

Thank you very much for your suggestions.
You are right, I've missed the first compiler error.

However, your code doesn't work (edition 2021).
The tried to return an impl Iterator already before, but I got the same error as when I compile your code:

> rustc --edition 2021 scale-trait.rs
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types
  --> scale-trait.rs:12:34
   |
12 |     fn scale(self, factor: T) -> impl Iterator<Item = T> {
   |                                  ^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information

error: aborting due to previous error

For more information about this error, try `rustc --explain E0562`.

That was the reason I used Map<> as return type, but obviously I couldn't resolve the bounds correctly.
You are right again, a free function (or the simple use of the closure in main() would be easier here, but I try to form a trait for educational purposes.

-> impl Trait in trait methods stabilized in 1.75. Try updating your compiler.

2 Likes

The 'static bound was unnecessary in my post above, because I also added move to the closure:

trait Scale<T>: Iterator<Item = T>
where
    T: Copy + std::ops::Mul<Output = T>,
    Self: Sized,
{
    fn scale(self, factor: T) -> impl Iterator<Item = T> {
        self.map(move |x: T| x * factor)
    }
}

impl<T, I> Scale<T> for I
where
    T: Copy + std::ops::Mul<Output = T>,
    I: Iterator<Item = T>,
{
}

And I think it is cleaner to remove the unnecessary bounds on T from the trait (avoiding repetition) and implement it for the bounds you need, allowing for the possibility of implementations with different bounds in the future:

trait Scale<T>: Iterator<Item = T> {
    fn scale(self, factor: T) -> impl Iterator<Item = T>;
}

impl<T, I> Scale<T> for I
where
    T: Copy + std::ops::Mul<Output = T>,
    I: Iterator<Item = T>,
{
    fn scale(self, factor: T) -> impl Iterator<Item = T> {
        self.map(move |x: T| x * factor)
    }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.