Alternatives to TryFrom

We don't like how half of TryFrom impls in std just use an None-equivalent but private error type. Like, why are the integer conversions forced to return a dummy struct instead of just returning None?

Our ideal TryFrom would look something like this:

trait TryFrom<T> {
  type Result: Try<Ok=Self>;
  fn try_from(t: T) -> Self::Result;
}

so that the integer conversions can just return Option<Self> instead. Is there a crate that provides a better TryFrom? This would let us personally use Foo::try_from(bar)? instead of Foo::try_from(bar).ok()? which would make our code much cleaner.

1 Like

num_traits::cast provides integer conversions traits/functions that return Option.

Like, why are the integer conversions forced to return a dummy struct instead of just returning None?

One benefit: If the error bubbles up to something that logs it, it displays as "out of range integral type conversion attempted".

2 Likes

But if it's giving you an Option then you can't make it bubble up because converting None to Err is technically not supposed to be possible?

Well, it is possible, you just have to specify explicitly what error do you want to see.

With ?, specifically. We know all the "try v2" proposals talk about NoneError leaking so there must be a way to do it, but it was never meant to be possible. But anyway, None doesn't bubble up like Error.

You can use Option::ok_or/ok_or_else to convert the option to a result, then bubble up errors.

1 Like

That NoneError leak is demonstrated here:

1 Like

I'm not sure why this isn't supposed to work. Tricky is constructible from any type, therefore the From::from conversion picks it up naturally in error position. What am I missing?

NoneError was a necessary component for the current Try design, but we really only intended to allow Option->Option and Result->Result. The expectation was that keeping NoneError unstable would allow it to be removed later in a new design, but Tricky shows that it's possible to use it abstractly even in stable code. So we're stuck with Option->Result too.

2 Likes

I was trying to illustrate one minor benefit of using Result over Option for fallible conversions: The library providing the conversion functions can also provide error descriptions that are sometimes useful for logging/debugging purposes.

Of course, there are also many use cases where this particular feature is not relevant.

2 Likes

Fair enough.

Uh, still, is there any crate that provides a TryFrom trait, but with Try instead of Result?

For numeric conversions, I still recommend the traits in num_traits::cast since they are already implemented for all primitive numeric types, as well as library types like BigInt and OrderedFloat.