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



我想要一个接受各种类型的函数,这些类型可以转换为我的特定类型。在类似的情况下,我会使用std::convert::Into(或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本地的trait。

  1. 修改孤儿规则,使远程trait的imps需要一个本地类型,要么是当前crate LT = LocalTypeConstructor<...>中定义的struct/enum/trait,要么是对本地类型LT = ... | &LT | &mut LT的引用。

因此,由于您没有在crate中创建Into trait,也没有创建Result类型,因此您会得到此错误。创建新类型解决了这个问题,因为它基本上是将非局部类型包装在局部类型中。

相关内容

最新更新