How to wrap FromStr::Err with anyhow::Error?

For concrete type like u64, the following code compiles successfully.

use anyhow::{Context, Result};
fn parse_u64(num_str: &str) -> Result<u64> {
    num_str
        .parse::<u64>()
        .with_context(|| format!("cannot parse {} as u64", num_str))
}

However the following code using generics does not compile.

use anyhow::{Context, Result};
use std::str::FromStr;

fn parse<F: FromStr>(num_str: &str) -> Result<F> {
    num_str
        .parse::<F>()
        .with_context(|| format!("cannot parse {}", num_str))
}

I got the following error.

error[E0599]: no method named `with_context` found for enum `std::result::Result<F, <F as std::str::FromStr>::Err>` in the current scope

Is there a way to FromStr:Err with anyhow::Error?

It fails because the FromStr trait does not require the error type to implement the Error trait. You could add this requirement:

use anyhow::{Context, Result};
use std::str::FromStr;
use std::error::Error;

fn parse<F: FromStr>(num_str: &str) -> Result<F>
where
    <F as FromStr>::Err: Error,
{
    num_str
        .parse::<F>()
        .with_context(|| format!("cannot parse {}", num_str))
}

In the case of u64, the compiler knows the exact error type, and can verify that it does in fact happen to be a kind of error.

1 Like

Thanks for your answer.
I tried it and the error message guided me to the following solution.

use anyhow::{Context, Result};
use std::error::Error;
use std::str::FromStr;

fn parse<F: FromStr>(num_str: &str) -> Result<F>
where
    <F as FromStr>::Err: Error + Send + Sync + 'static,
{
    num_str
        .parse::<F>()
        .with_context(|| format!("cannot parse {}", num_str))
}