为什么使用 Option::map 到 Box::new 特征对象不起作用?

Why does using Option::map to Box::new a trait object not work?

trait FooTrait {}

struct FooStruct;

impl FooTrait for FooStruct {}

fn main() {
    let maybe_struct: Option<dyn FooStruct> = None;

    //  Does not compile
    let maybe_trait: Option<Box<dyn FooTrait>> = maybe_struct.map(Box::new);

    // Compiles fine
    let maybe_trait: Option<Box<dyn FooTrait>> = match maybe_struct {
        Some(s) => Some(Box::new(s)),
        None => None,
    };
}
error[E0404]: expected trait, found struct `FooStruct`
 --> src/main.rs:9:34
  |
9 |     let maybe_struct: Option<dyn FooStruct> = None;
  |                                  ^^^^^^^^^ not a trait

Rustc 1.23.0。为什么第一种方法不能编译?我是不是遗漏了一些明显的东西,或者……嗯?

Box::new 仅适用于大小类型;也就是说,它采用大小类型 T 和 returns Box<T> 的值。在某些地方 Box<T> 可以是 coerced into a Box<U> (if T: Unsize<U>).

这种强制转换不会发生在 .map(Box::new) 中,但会发生在 Some(Box::new(s)) 中;后者与Some(Box::new(s) as Box<FooTrait>).

基本相同

您可以创建(每晚)您自己的盒子构造函数,returns 像这样的未调整大小的盒子:

#![feature(unsize)]

fn box_new_unsized<T, U>(v: T) -> Box<U>
where
    T: ::std::marker::Unsize<U>,
    U: ?Sized,
{
    Box::<T>::new(v)
}

并像 .map(box_new_unsized) 一样使用它。参见 Playground