首页 > 解决方案 > 为另一个特征项目类型实现一个特征

问题描述

在返回 Result 时,我需要将解析错误转换为我自己的错误类型。简化后,如下所示:

enum MyError {
    Parse,
    ...,
}

fn process<R: FromStr>(s: &str) -> Result<(), MyError> {
    Ok(s.parse::<R>()?)
}

为了使上述工作,应实施 From 特征。这不起作用:

impl From<std::str::FromStr::Err> for MyError {
    fn from(e: std::str::FromStr::Err) -> MyError {
        MyError::Parse
    }
}

编译器诊断:

help: use fully-qualified syntax: `<Type as std::str::FromStr>::Err`

但我不知道Type这里的确切情况。重点是允许从所有可能的错误中进行转换。

标签: error-handlingrust

解决方案


类型FromStr::Err是特征的关联类型FromStr。的每个实现FromStr都有自己的关联类型,并且这种类型是完全不受约束的——它可以是任何类型。这意味着您需要从任何类型的转换MyError来实现您想要的:

impl<T> From<T> for MyError {
    fn from(e: T) -> MyError {
        MyError::Parse
    }
}

但是,一致性规则不允许这种实现——它与标准库From<T>中任何类型的实现相冲突。T即使这个实现被允许,它也不会真正做你想要的——任何错误类型都会被转换为MyError::Parse,而不仅仅是解析错误。

一种可能的解决方法是为解析错误类型引入标记特征:

trait ParseError {}

impl<T: ParseError> From<T> for MyError {
    fn from(e: T) -> MyError {
        MyError::Parse
    }
}

然后,您可以为所有解析错误类型实现此标记特征:

impl ParseError for std::str::ParseBoolError {}
impl ParseError for std::num::ParseFloatError {}
impl ParseError for std::num::ParseIntError {}
impl ParseError for std::net::AddrParseError {}
impl ParseError for std::char::ParseCharError {}

推荐阅读