I am trying to make a generic implementation of TryFrom
for an object T
whenever T
implements a TryFrom
. However, I am struggling to pass anyhow::Error
s.
In the code below, I can convert a Generic<T>
into a ValueContainer
so long as &usize: TryFrom<T>
. It almost does what I want, but does not allow me to properly handle errors from the &usize: TryFrom<T>
.
#[cfg(test)]
mod question {
use std::fmt::Debug;
use anyhow::anyhow;
#[derive(Debug)]
struct Generic<T: Debug>(T);
#[derive(Debug)]
struct Foo(usize);
#[derive(Debug)]
struct ValueContainer<'a>(&'a usize);
impl TryFrom<Foo> for &usize {
type Error = anyhow::Error;
fn try_from(value: Foo) -> Result<Self, Self::Error> {
if value.0 > 5 {
Ok(&5)
} else {
Err(anyhow!("Value must be bigger"))
}
}
}
impl<'a, T> TryFrom<Generic<T>> for ValueContainer<'a>
where
for<'b> &'b usize: TryFrom<T>,
T: Debug,
for<'b> anyhow::Error: From<<&'b usize as TryFrom<T>>::Error>,
{
type Error = anyhow::Error;
fn try_from(value: Generic<T>) -> Result<Self, Self::Error> {
// XXX: Can't do this?
// let value: &usize = value.0.try_into().unwrap();
match <&usize as TryFrom<T>>::try_from(value.0) {
Ok(v) => Ok(ValueContainer(v)),
Err(_) => {
// XXX: I would like this to be the error from the try_into above
// but there is an error `<&usize as TryFrom<T>>::Error` cannot be formatted with the default formatter`
return Err(anyhow!("Error converting type"));
}
}
}
}
#[test]
fn test_try_into() {
let value = Generic(Foo(10));
let value: Result<ValueContainer, anyhow::Error> = value.try_into();
dbg!(&value);
let value = Generic(Foo(2));
let value: Result<ValueContainer, anyhow::Error> = value.try_into();
dbg!(&value);
}
}
I am not able to use value.try_into()?
in my implementation of TryFrom<Generic<T>>
. Uncommenting the let value: &usize = value.try_into()?;
produces the error
error[E0271]: type mismatch resolving `<&usize as TryFrom<Generic<T>>>::Error == <&usize as TryFrom<T>>::Error`
--> lib-doenetml-core/src/core/props/prop_view.rs:140:40
|
140 | let value: &usize = value.try_into()?;
| ^^^^^^^^ expected `Infallible`, found associated type
|
= note: expected enum `Infallible`
found associated type `<&usize as TryFrom<T>>::Error`
= help: consider constraining the associated type `<&usize as TryFrom<T>>::Error` to `Infallible`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
It seems like Using TryInto generics with anyhow::Error might be relevant, and it inspired me to add for<'b> anyhow::Error: From<<&'b usize as TryFrom<T>>::Error>
, but that didn't seem to work...
Any ideas on how I can allow value.try_into()?
directly?
?
will work if you will fix your typo and add .0
.
unwrap()
requires the Debug
trait for the error (because it prints it on failure), so you need to add this bound:
impl<'a, T> TryFrom<Generic<T>> for ValueContainer<'a>
where
for<'b> &'b usize: TryFrom<T>,
T: Debug,
for<'b> anyhow::Error: From<<&'b usize as TryFrom<T>>::Error>,
for<'b> <&'b usize as TryFrom<T>>::Error: Debug,
{
type Error = anyhow::Error;
fn try_from(value: Generic<T>) -> Result<Self, Self::Error> {
// XXX: Can't do this?
let value: &usize = value.0.try_into().unwrap();
Ok(ValueContainer(value))
}
}