使用 Result::map 和 Box 时无法推断类型

龙方淞*_*龙方淞 2 rust

为什么这不会编译?

trait T {}

fn f<U: 'static + T, V, E>(f2: V) -> impl Fn() -> Result<Box<dyn T>, E>
where
    V: Fn() -> Result<U, E>,
{
    move || -> Result<Box<dyn T>, E> { f2().map(Box::new) }
}
Run Code Online (Sandbox Code Playgroud)

错误信息是:

error[E0308]: mismatched types
 --> src/lib.rs:7:40
  |
7 |     move || -> Result<Box<dyn T>, E> { f2().map(Box::new) }
  |                                        ^^^^^^^^^^^^^^^^^^ expected trait T, found type parameter
  |
  = note: expected type `std::result::Result<std::boxed::Box<(dyn T + 'static)>, _>`
             found type `std::result::Result<std::boxed::Box<U>, _>`
  = help: type parameters must be constrained to match other types
  = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
Run Code Online (Sandbox Code Playgroud)

这个版本没问题:

trait T {}

fn f<U: 'static + T, V, E>(f2: V) -> impl Fn() -> Result<Box<dyn T>, E>
where
    V: Fn() -> Result<U, E>,
{
    move || -> Result<Box<dyn T>, E> {
        match f2() {
            Ok(result) => Ok(Box::new(result)),
            Err(e) => Err(e),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在我看来,(dyn T + 'static)U是一样的;我对吗?

我正在使用rustc 1.39.0-nightly (f0b58fcf0 2019-09-11).

Sta*_*eur 6

这是一个限制,我不知道它是否会在某一天编译。原因是 Rust 不知道在这两种Result类型之间进行转换,(dyn T + 'static)并且U是完全不同的东西。如果这可以接受,您可以这样做f2().map(|x| Box::new(x) as _)

强制转换将允许编译器在将其放入结果之前转换U(dyn T + 'static),我们不需要明确编译器推断将为我们执行的强制转换类型(在大多数情况下)。

trait 对象可以从一个指向具体类型的指针获得,该类型通过强制转换来实现 trait(例如 &x as &Foo)

参见本书的动态调度部分(在新书中没有找到任何信息)。