[英]Rust ? operator does not work with Into<T> trait
I was writting a function to flat a Result.我正在写一个 function 来平坦一个结果。 This is what I got.
这就是我得到的。
type BoxDyn = Box<dyn Error + Send + Sync>;
fn flat_result<U, T, G>(r: Result<Result<U, G>, T>) -> Result<U, BoxDyn>
where
T: Into<BoxDyn>,
G: Into<BoxDyn>,
{
match r {
Err(x) => Err(x.into()),
Ok(x) => match x {
Err(x) => Err(x.into()),
Ok(x) => Ok(x),
},
}
}
It works fine.它工作正常。 But I should be able to write it using two
?
但我应该可以用两个来写它
?
like this.像这样。
type BoxDyn = Box<dyn Error + Send + Sync>;
fn flat_result<U, T, G>(r: Result<Result<U, G>, T>) -> Result<U, BoxDyn>
where
T: Into<BoxDyn>,
G: Into<BoxDyn>,
{
Ok(r??)
}
When I try this, I get this error:当我尝试这个时,我得到这个错误:
`G` cannot be shared between threads safely
required because of the requirements on the impl of `From<G>` for `Box<dyn std::error::Error + Send + Sync>`
required because of the requirements on the impl of `FromResidual<Result<Infallible, G>>` for `Result<U, Box<dyn std::error::Error + Send + Sync>>`
But it seems to me that it should not happen because the documentation says that the ?
但在我看来,它不应该发生,因为文档说
?
is equivalent to a match expression, where the Err(err) branch expands to an early return Err(From::from(err))
. is equivalent to a match expression, where the Err(err) branch expands to an early return Err(From::from(err))
。 And also From<T> for U implies Into<U> for T
.还有
From<T> for U implies Into<U> for T
。 So it would not matter What G or T are, if they implement Into it should work.因此,G 或 T 是什么并不重要,如果他们实施 Into 它应该可以工作。 What is the problem?
问题是什么?
You are right that From
implies Into
but not that into
implies From
.你是对的
From
暗示Into
但不是into
暗示From
。 And remember that ?
还记得
?
uses From
, not Into
.使用
From
,而不是Into
。
As it happens there is this impl
in the standard library that gets in the way:碰巧的是,标准库中有这个
impl
阻碍了:
impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a>
Since your BoxDyn
alias is exactly that with 'a = 'static
, you have an implementation for From<E>
.由于您的
BoxDyn
别名与'a = 'static
完全相同,因此您有一个From<E>
的实现。 But for that to work your error types T
and G
has to satisfy Error + Send + Sync + 'a
.但是要使您的错误类型
T
和G
起作用,必须满足Error + Send + Sync + 'a
。 But your only constraints are that they are Into<Error>
that is actually unrelated to what is needed.但是您唯一的限制是它们是
Into<Error>
实际上与所需内容无关。 Remember that From
implies Into
but Into
does not imply From
.请记住,
From
暗示Into
但Into
并不暗示From
。
It works if you write instead:如果您改为编写它,它会起作用:
fn flat_result<U, T, G>(r: Result<Result<U, G>, T>) -> Result<U, BoxDyn>
where
T: Error + Send + Sync + 'static,
G: Error + Send + Sync + 'static,
{
Ok(r??)
}
But I think that the proper way to write that would be to require the From
trait:但我认为正确的写法是要求
From
特征:
fn flat_result<U, T, G>(r: Result<Result<U, G>, T>) -> Result<U, BoxDyn>
where
BoxDyn: From<T> + From<G>,
{
Ok(r??)
}
Why does it work with the manual implementation?为什么它适用于手动实现? Well, because you are using
Into
instead of From
of course.好吧,因为您当然使用的是
Into
而不是From
。 Change it to BoxDyn::from(x)
and it will fail just the same.将其更改为
BoxDyn::from(x)
,它同样会失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.