我如何使用 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 本地的特征。
- 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 = ... | < | &mut LT
.
因此,由于您没有在您的板条箱中创建 Into
特征,也没有创建 Result
类型,所以您会收到此错误。创建一个新类型可以解决这个问题,因为它基本上将非本地类型包装在本地类型中。
我想要一个接受多种类型的函数,这些类型可以转换为我的特定类型。在类似情况下,我会使用 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 本地的特征。
- 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 typeLT = ... | < | &mut LT
.
因此,由于您没有在您的板条箱中创建 Into
特征,也没有创建 Result
类型,所以您会收到此错误。创建一个新类型可以解决这个问题,因为它基本上将非本地类型包装在本地类型中。