【问题标题】:Why can't I push into a Vec of dyn Trait unless I use a temporary variable?除非我使用临时变量,否则为什么我不能推入 Vec 的 dyn Trait?
【发布时间】:2020-09-10 07:35:57
【问题描述】:

这是我的代码:

use std::rc::{Rc, Weak};
use std::cell::RefCell;

trait Trait {}

fn push<E: Trait>(e: E) {
    let mut v: Vec<Rc<RefCell<Box<dyn Trait>>>> = Vec::new();
    
    // let x = Rc::new(RefCell::new(Box::new(e)));
    // v.push(x); // error

    v.push(Rc::new(RefCell::new(Box::new(e)))); // works fine
}

v.push(x) 引发此错误:

error[E0308]: mismatched types
  --> src/main.rs:12:12
   |
7  | fn push<E: Trait>(e: E) {
   |         - this type parameter
...
12 |     v.push(x);
   |            ^ expected trait object `dyn Trait`, found type parameter `E`
   |
   = note: expected struct `std::rc::Rc<std::cell::RefCell<std::boxed::Box<dyn Trait>>>`
              found struct `std::rc::Rc<std::cell::RefCell<std::boxed::Box<E>>>`

但是,如果我将值(使用完全相同的值和类型构造)直接推入向量中,它编译不会出错。

那么为什么第一个版本不能编译呢?我应该做些什么改变,以便在将其推入向量之前使用x

【问题讨论】:

标签: rust polymorphism traits parametric-polymorphism trait-objects


【解决方案1】:

这一切都在类型推断中。当你写:

v.push(Rc::new(RefCell::new(Box::new(e))));

Rust 可以从该上下文中看出RefCell::new() 的参数必须是Box&lt;dyn Trait&gt;,因此尽管提供了Box&lt;E&gt;,但它会将其强制转换为前一种类型。另一方面,当你写这个时:

let x = Rc::new(RefCell::new(Box::new(e)));
v.push(x); // compile error

Rust 首先推断出Rc&lt;RefCell&lt;Box&lt;E&gt;&gt;&gt; 类型的x,您不能再将push 转换为Rc&lt;RefCell&lt;Box&lt;dyn Trait&gt;&gt;&gt;vec。您可以通过在 let 绑定中添加显式类型注释来更改此设置,以预先告诉 Rust 您确实需要 Rc&lt;RefCell&lt;Box&lt;dyn Trait&gt;&gt;&gt;

use std::rc::{Rc, Weak};
use std::cell::RefCell;

trait Trait {}

fn push<E: Trait>(e: E) {
    let mut v: Vec<Rc<RefCell<Box<dyn Trait>>>> = Vec::new();

    let x: Rc<RefCell<Box<dyn Trait>>> = Rc::new(RefCell::new(Box::new(e)));
    v.push(x); // compiles
}

playground

这里要理解的重要一点是E dyn Trait 不同ETrait 的一些已知具体实现,而dyn Trait 是一个特征对象,其底层具体实现已被删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2023-03-29
    • 1970-01-01
    • 2018-12-11
    相关资源
    最近更新 更多