为什么下面的代码是错误的?有一个从[T; N]Vec<T>的全面实现,那么在这个上下文中,为什么dyn Foo不匹配Fooable呢?有没有不涉及克隆Fooable的变通办法?

trait Foo {}

struct Fooable {}

impl Foo for Fooable {}

pub fn main() {
    let bar: Vec<Box<dyn Foo>> = [
        Box::new(Fooable {}),
    ].into();
}

错误:

error[E0277]: the trait bound `Vec<Box<dyn Foo>>: From<[Box<Fooable>; 1]>` is not satisfied
  --> src/main.rs:10:7
   |
10 |     ].into();
   |       ^^^^ the trait `From<[Box<Fooable>; 1]>` is not implemented for `Vec<Box<dyn Foo>>`
   |
   = help: the following other types implement trait `From<T>`:
             <Vec<T, A> as From<Box<[T], A>>>
             <Vec<T, A> as From<VecDeque<T, A>>>
             <Vec<T> as From<&[T]>>
             <Vec<T> as From<&mut [T]>>
             <Vec<T> as From<BinaryHeap<T>>>
             <Vec<T> as From<Cow<'a, [T]>>>
             <Vec<T> as From<[T; N]>>
             <Vec<u8> as From<&str>>
           and 2 others
   = note: required because of the requirements on the impl of `Into<Vec<Box<dyn Foo>>>` for `[Box<Fooable>; 1]`

Playground

推荐答案

您可以通过手动投射该框来修复错误,如下所示:

trait Foo {}

struct Fooable {}

impl Foo for Fooable {}

pub fn main() {
    let bar: Vec<Box<dyn Foo>> = [
        // Turn a Box<Fooable> into a Box<dyn Foo>
        Box::new(Fooable {}) as Box<dyn Foo>,
    ].into();
}

请记住,默认情况下,Rust Builds直接用对实现的调用替换特征方法调用(如果存在的话).对象的"类型"只在编译时存在,在运行时没有类型.dyn种类型是不同的.它们存储一些额外的数据,以便在运行时找到要调用的方法的实际变体.

为什么直接赋值给数组是可以的呢?

当您定义这样的整数数组时:

// this works
let k:[i8;3] = [1,2,3]

这里没有发生转换.即使数字默认为i32,数组中的数字将被解释为i8个值.

在这个例子中是一样的:

let k:Box<dyn T> = Box::new(V{});

V{}Box<dyn T>的转换需要转换,但编译器可以通过从一开始就将右侧解释为Box<dyn T>来避免转换.

这也适用于数组,但如果存在一定程度的间接性,则不适用:

// works
let k:[Box<dyn T>;1] = [Box::new(V{})]
// does not work
let b = [Box::new(Fooable {})];
let e:[Box<dyn Foo>;1] = b;

这也是这一点有效的原因:

let bar: Vec<Box<dyn Foo>> = [
    Box::new(Fooable {}) as Box<dyn Foo>,
    Box::new(Fooable {}),
    Box::new(Fooable {}),
].into()

即使我们在第一个元素上只有as Box<dyn Foo>,这也改变了解释整个数组的方式.

Rust相关问答推荐

无需通过ASIO输入音频,并使用cpal进行反馈示例

如何使用syn插入 comments ?

支持TLS的模拟HTTP服务器

如何正确地将App handler传递给Tauri中的其他模块?

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

对于已经被认为是未定义行为的相同数据,纯粹存在`&;[u32]`和`&;mut[u32]`吗?

如何设置activx websocket actorless的消息大小限制?

Cargo.toml:如何有条件地启用依赖项功能?

Boxing 如何将数据从堆栈移动到堆?

注释闭包参数强调使用高阶排定特征界限

有没有办法隐式绑定 let/match 操作的成员?

为什么不可变特征的实现可以是可变的?

具有在宏扩展中指定的生命周期的枚举变体数据类型

返回引用字符串的future

Rust 中函数的类型同义词

将一片字节复制到一个大小不匹配的数组中

Rustlings 切片原语

实现不消费的迭代器

将 (T, ()) 转换为 T 安全吗?

调试打印导致字段类型为 std::rc::Rc 的 struct 的堆栈溢出