Trait From not implemented for generic method parameter

I wrote this simplified snippet of what I would like to do and I don't understand why the compile time error

error[E0277]: the trait bound `Tag: std::convert::From<&T>` is not satisfied
  --> src/main.rs:58:25
   |
58 |     tags.iter().map(|t| Tag::from(t)).collect()
   |                         ^^^^^^^^^ the trait `std::convert::From<&T>` is not implemented for `Tag`
   |
   = note: required by `std::convert::From::from`

is thrown when clearly From is implemented for both PostTag and EventTag.

Can anybody please give me some advice?

Your trait bounds aren’t quite right. The type in the passed Vec is the owned type and you are trying to convert a reference type so the bound should explicitly be on the reference type which is what the where clause is doing here. The for<‘a> syntax is called a higher ranked trait bound and is needed here because the lifetime for the borrows of item in the iterator is not known by the caller.

(Also I changed the argument to a slice to be more idiomatic)

fn process<T>(tags: &[T]) -> Vec<Tag> where for<‘a> &’a T: Into<Tag> {
    tags.iter().map(|t| Tag::from(t)).collect()
}

1 Like

Thanks for your response!

Okay, I understand the logic behind your explanation but the suggested fix doesn't solve the compiler error, or am I getting something wrong here?
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=6c2843203eb45855f3898dab5349d023

1 Like

Oh I forgot I changed from to into in map. I’m not sure if type inference can pick up the from method here. The trait bound is on Into so into would be the logical method to call.

fn process<T>(tags: &[T]) -> Vec<Tag> where for<‘a> &’a T: Into<Tag> {
    tags.iter().map(|t| t.into()).collect()
}
1 Like

Thank you!
Makes sense again.