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");
1 Like

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

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

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

2 Likes

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.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.