如何使用 std::convert::Into 转换可能失败的内容? [英] How can I use std::convert::Into to convert something that might fail?
问题描述
我想要一个接受多种类型的函数,这些类型可以转换为我的特定类型.在类似的情况下,我会使用 std::convert::Into
(或 std::convert::From
):
pub struct MyThing;impl'a>进入<MyThing>对于 &'a str {fn into(self) ->我的东西 {我的东西}}fn main() {}
作为一个额外的问题,在我的特定情况下,转换可能会失败.通常,我会使用 Result
表示可能失败的操作.将两个概念结合在一起:
pub struct MyThing;酒吧结构错误;impl'a>进入<结果<MyThing, Error>>对于 &'a str {fn into(self) ->结果{如果 self.len() % 2 == 0 {好的(我的事情)} 别的 {错误(错误)}}}fn main() {}
不幸的是,这似乎违反了一致性规则:
error: impl 未引用此 crate 中定义的任何类型;只能实现当前 crate 中定义的特性任意类型 [E0117]
我发现我可以创建自己的特定特征:
struct MyThing;结构错误;特质 IntoMyThing {fn into(self) ->结果;}impl'a>IntoMyThing for &'a str {fn into(self) ->结果{如果 self.len() % 2 == 0 {好的(我的事情)} 别的 {错误(错误)}}}fn main() {}
甚至更通用的特征:
struct MyThing;结构错误;特质MaybeInto<T,E>{fn into(self) ->结果<T,E>;}impl'a>MaybeInto<MyThing, Error>对于 &'a str {fn into(self) ->结果{如果 self.len() % 2 == 0 {好的(我的事情)} 别的 {错误(错误)}}}fn main() {}
但是有没有办法重用标准库中的组件来实现我的目标?
由于连贯性规则,这是不可能的,这使得这样的事情非常不方便,因为除非您创建新类型,否则您无法做到对于其中一种类型,Result
或 &str
.有关详细信息,请参阅 RFC #1023.
简而言之,根据该 RFC 规定的新规则,您不能为不是 crate 本地的类型实现不是 crate 本地的特征.
<块引用>- 修改孤立规则,以便远程特征的实现需要一个本地类型,该类型要么是当前 crate 中定义的结构/枚举/特征
LT = LocalTypeConstructor<...>
或引用到本地类型LT = ... |< |&mut LT
.
因此,由于您没有在 crate 中创建 Into
特征,也没有在 Result
类型中创建,因此您会收到此错误.创建一个新类型可以解决这个问题,因为它基本上将非本地类型包装在本地类型中.
I would like a function that accepts a variety of types that can be converted to my specific type. In similar cases, I'd use std::convert::Into
(or std::convert::From
):
pub struct MyThing;
impl<'a> Into<MyThing> for &'a str {
fn into(self) -> MyThing {
MyThing
}
}
fn main() {}
As an extra wrinkle, in my specific case, the conversion can potentially fail. Normally, I'd use Result
to represent an operation that may fail. Combining the two concepts together:
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() {}
Unfortunately, this seems to run afoul of coherence rules:
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]
I see that I could create my own specific trait:
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() {}
Or even a more-generic trait:
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() {}
But is there any way to reuse components from the standard library to accomplish my goal?
This isn't possible as-is due to coherence rules, which makes things like this pretty inconvenient, because you can't do it unless you create a newtype for one of the types, either the Result
or the &str
. See RFC #1023 for more information.
In short, based on the new rules stipulated by that RFC, you cannot implement a trait that's not local to the crate for a type that's not local to the 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
.
So since you didn't create the Into
trait in your crate nor the Result
type, you get this error. Creating a new type fixes this because it basically wraps a non-local type in a local type.
这篇关于如何使用 std::convert::Into 转换可能失败的内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!