除非我使用临时变量,否则为什么我不能推入 dyn Trait 的 Vec?
Why can't I push into a Vec of dyn Trait unless I use a temporary variable?
这是我的代码:
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
?
都在类型推断中。当你写:
v.push(Rc::new(RefCell::new(Box::new(e))));
Rust 可以从上下文中得知 RefCell::new()
的参数必须是 Box<dyn Trait>
,因此尽管提供了 Box<E>
,它还是将其强制转换为前一种类型。另一方面,当您这样写时:
let x = Rc::new(RefCell::new(Box::new(e)));
v.push(x); // compile error
Rust 首先推断 x
类型 Rc<RefCell<Box<E>>>
并且您不能再将其 push
转换为 Rc<RefCell<Box<dyn Trait>>>
的 vec
。您可以通过在 let
绑定中放置一个显式类型注释来更改此设置,以预先告诉 Rust 您确实需要 Rc<RefCell<Box<dyn Trait>>>
:
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
}
这里要理解的重要一点是 E
不同于 和 dyn Trait
。 E
是 Trait
的一些已知具体实现,而 dyn Trait
是一个特性对象,其底层具体实现已被删除。
这是我的代码:
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
?
都在类型推断中。当你写:
v.push(Rc::new(RefCell::new(Box::new(e))));
Rust 可以从上下文中得知 RefCell::new()
的参数必须是 Box<dyn Trait>
,因此尽管提供了 Box<E>
,它还是将其强制转换为前一种类型。另一方面,当您这样写时:
let x = Rc::new(RefCell::new(Box::new(e)));
v.push(x); // compile error
Rust 首先推断 x
类型 Rc<RefCell<Box<E>>>
并且您不能再将其 push
转换为 Rc<RefCell<Box<dyn Trait>>>
的 vec
。您可以通过在 let
绑定中放置一个显式类型注释来更改此设置,以预先告诉 Rust 您确实需要 Rc<RefCell<Box<dyn Trait>>>
:
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
}
这里要理解的重要一点是 E
不同于 和 dyn Trait
。 E
是 Trait
的一些已知具体实现,而 dyn Trait
是一个特性对象,其底层具体实现已被删除。