简体   繁体   English

Rust? 运算符不适用于 Into<t> 特征</t>

[英]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 .但是要使您的错误类型TG起作用,必须满足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暗示IntoInto并不暗示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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM