Is it possible to provide type annotation for `try_into()`?

I'm writing a library which provides an "element" structure. I have a bunch of parsing functions for interpreting the element's value as different types but I'm working on changing these to be more idiomatic for rust by implementing TryFrom instead.

struct Element {
  //...
  value: Vec<u8>,
}

// old
impl Element {
  pub fn parse_strings(&self) -> Result<String, Error> {
    //...
  }
}

// new
impl TryFrom<&Element> for Vec<String> {
  type Error = ();
  fn try_from(value: &Element) -> Result<Self, Self::Error> {
    //...
  }
}

However when I do this I don't seem to be able to use try_into() on the element in some situations as I get an error about needing a type annotation. When I try adding a type annotation I get an error about an unexpected type annotation.

let item_scs: String = item
        .get_child(tags::SpecificCharacterSet.tag)
        .expect("Item should have SCS")
        .as_element()
//        .parse_strings()?
        .try_into()?
        .into_iter()
        .filter(|cs_entry: &String| !cs_entry.is_empty())
        .nth(0)
        .expect("Should have at least one value for SCS");

---

error[E0282]: type annotations needed
// instead with .try_into::<Vec<String>>()?
error[E0107]: wrong number of type arguments: expected 0, found 1

Is there no way to provide type annotations in this manner? I can split the assignment into multiple assignments but I would rather not do this

let item_scs_values: Vec<String> = item
        .get_child(tags::SpecificCharacterSet.tag)
        .expect("Item should have SCS")
        .as_element()
        .try_into()?;

let item_scs: String = item_scs_values
        .into_iter()
        .filter(|cs_entry: &String| !cs_entry.is_empty())
        .nth(0)
        .expect("Should have at least one value for SCS");

To add a type annotation, you'll need to write the following instead of expr.try_into():

TryInto::<Vec<String>>::try_into(expr)

Ah thanks - so I think that means there's no way to inline the try_into() call like I could parse_string() before, right?

Right, there's no clean-looking way to fit it in the middle of a chain of method calls.

you could make a new trait,

trait GenericTryInto {
    fn try_into_gen<T>(self) -> Result<T, Self::Error> where Self: TryInto<T> {
        self.try_into()
    }
}
impl<T: ?Sized> GenericTryInto for T {}

Then you can use it like,

foo.try_into_gen::<Bar>();

playground

1 Like

Oh cool! Thanks for the suggestion. Right now I'm only chaining calls like this in test code but I think I'll add something like that if it does end up being useful in the public API.