我如何使用 std::convert::Into 来转换可能会失败的内容?

How can I use std::convert::Into to convert something that might fail?

我想要一个接受多种类型的函数,这些类型可以转换为我的特定类型。在类似情况下,我会使用 std::convert::Into (or std::convert::From):

pub struct MyThing;

impl<'a> Into<MyThing> for &'a str {
    fn into(self) -> MyThing { 
        MyThing
    }
}

fn main() {}

作为一个额外的问题,在我的具体情况下,转换可能会失败。通常,我会使用 Result 来表示可能会失败的操作。将这两个概念结合在一起:

pub struct MyThing;
pub struct Error;

impl<'a> Into<Result<MyThing, Error>> for &'a str {
    fn into(self) -> Result<MyThing, Error> { 
        if self.len() % 2 == 0 {
            Ok(MyThing)
        } else {
            Err(Error)
        }
    }
}

fn main() {}

不幸的是,这似乎 运行 违反了一致性规则:

error: the impl does not reference any types defined in this crate;
only traits defined in the current crate can be implemented for
arbitrary types [E0117]

我发现我可以创建自己的特定特征:

struct MyThing;
struct Error;

trait IntoMyThing {
    fn into(self) -> Result<MyThing, Error>;
}

impl<'a> IntoMyThing for &'a str {
    fn into(self) -> Result<MyThing, Error> { 
        if self.len() % 2 == 0 {
            Ok(MyThing)
        } else {
            Err(Error)
        }
    }
}

fn main() {}

或者更通用的特征:

struct MyThing;
struct Error;

trait MaybeInto<T, E> {
    fn into(self) -> Result<T, E>;
}

impl<'a> MaybeInto<MyThing, Error> for &'a str {
    fn into(self) -> Result<MyThing, Error> { 
        if self.len() % 2 == 0 {
            Ok(MyThing)
        } else {
            Err(Error)
        }
    }
}

fn main() {}

但是有什么方法可以重用标准库中的组件来实现我的目标吗?

由于一致性规则,这不可能按原样进行,这使得这样的事情非常不方便,因为除非您为其中一种类型创建新类型,否则您无法做到这一点,Result&str。有关详细信息,请参阅 RFC #1023

简而言之,根据该 RFC 规定的新规则,您不能为非 crate 本地的类型实现非 crate 本地的特征。

  1. Modify the orphan rules so that impls of remote traits require a local type that is either a struct/enum/trait defined in the current crate LT = LocalTypeConstructor<...> or a reference to a local type LT = ... | &LT | &mut LT.

因此,由于您没有在您的板条箱中创建 Into 特征,也没有创建 Result 类型,所以您会收到此错误。创建一个新类型可以解决这个问题,因为它基本上将非本地类型包装在本地类型中。