1
votes

When working with the Serde crate in Rust I tried to add a #[serde(try_from = String)] container attribute to a type that implements FromStr and thus can be parsed from string. Unfortunately this seems not enough for Serde, from the compiler error message it becomes obvious that I have to manually implement TryFrom<String>, too.

Why is TryFrom<String> not implemented automatically for all types that implement FromStr? And why is there a separate trait for fallible conversion from strings? What is the difference between these two traits?

2
I think the answer is an average "for historical reasons": AFAIK FromStr is much older and TryFrom was added only later. However, the trait autoimplementation that you expected sounds logical, maybe there were technical reasons and it could not be easily done. - Zólyomi István
You might find it useful that serde_with allows you to automatically (de)serialize using FromStr and Display, and has many other convenience features - trentcl
Thanks for the link to serde_with. I will take a look, but as my project targets WASM I'm rather sensitive to additional dependencies in case they increase output size. - blerontin

2 Answers

4
votes

FromStr was stable in Rust 1.0, TryFrom was stablized in Rust 1.34; it would be very hard to use the trait before it existed.

Why is TryFrom<String> not implemented automatically for all types that implement FromStr?

This would cause ambiguity with types that have already implemented both TryFrom and FromStr. An advanced form of specialization would be needed to allow this.

why is there a separate trait for fallible conversion from strings?

FromStr creates an owned value from a borrowed string slice (&str), so it's semantically different from taking ownership of a String. TryFrom<String> would allow you to reuse the memory allocated for the String.

The closer analog would be impl<'a> TryFrom<&'a str> for ..., but having the lifetime in the trait makes using it more complicated in "simple" cases of parsing a value out of a string.

See also:

0
votes

TryFrom is a generic trait, which can be implemented for "any" type. From the documentation:

Simple and safe type conversions that may fail in a controlled way under some circumstances.

Type -> Type

It also provides an auto implementation of TryInto.

FromStr is used mostly to parse types, also as per the documentation:

FromStr's from_str method is often used implicitly, through str's parse method.

str -> Type

Implement it to be used by str::parse