Home > Net >  The trait bound `String: From<&T>` is not satisfied when my T is bound with Into<String>
The trait bound `String: From<&T>` is not satisfied when my T is bound with Into<String>

Time:10-12

I have the following code,

impl<T: Debug   Into<String>   Clone> TryFrom<Vec<T>> for Positionals {
  type Error = &'static str;
  fn try_from(mut vec: Vec<T>) -> Result<Self, Self::Error> {
    let mystr: String = vec.get(0).unwrap().into();

And that code is producing this error,

error[E0277]: the trait bound `String: From<&T>` is not satisfied
  --> bin/seq.rs:21:43
   |
21 |         let mystr: String = vec.get(0).unwrap().into();
   |                                                 ^^^^ the trait `From<&T>` is not implemented for `String`
   |
   = note: required because of the requirements on the impl of `Into<String>` for `&T`
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement

I'm confused as to why this is generating an error because I have a trait bound on Vec<T> such that T must implement Into<String>, what else is required? I don't understand why this is, I remove the into(), I get

let mystr: String = vec.get(0).unwrap();
           ------   ^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&T`

How can I get my T in Vec<T> to String? The reason why I'm doing Vec<T> and not Vec<String> is because I want to support Vec<&str> too.

CodePudding user response:

The problem with your code is that your vector gives you references, i.e. &String. While Into<String> is trivially implemented for String, it is not implemented for &String, which would require cloning. You could implement the compiler's suggestion and add a where T: From<&String>, but it'd require additional fiddling with lifetimes and would again not support &str.

To support both &str and String, you can use AsRef<str>:

impl<T: Debug   Clone   AsRef<str>> TryFrom<Vec<T>> for Positionals {
    type Error = &'static str;
    fn try_from(mut vec: Vec<T>) -> Result<Self, Self::Error> {
        let mystr: String = vec[0].as_ref().into();
        todo!()
    }
}

With that both of the following compile:

Positionals::try_from(vec!["foo",]);
Positionals::try_from(vec!["foo".to_owned(),]);

Playground

Side note: you can use vec[0] instead of vec.get(0).unwrap(). (To prevent an unwanted move out of the vector, just add a borrow, i.e. &vec[0].)

  • Related