[英]Why can't I push into a Vec of dyn Trait unless I use a temporary variable?
This is my code:这是我的代码:
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
}
The v.push(x)
raises this error: 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>>>`
But if I push the value (constructed with the exact same value and types) directly into the vector it compiles without error.但是,如果我将值(用完全相同的值和类型构造)直接推送到向量中,它会编译而不会出错。
So why doesn't the first version compile?那么为什么第一个版本不编译呢? And what should I change to make it so that I can use x
before pushing it into the vector?我应该改变什么来使它可以在将x
推入向量之前使用它?
It's all in the type inference.这一切都在类型推断中。 When you write:当你写:
v.push(Rc::new(RefCell::new(Box::new(e))));
Rust can tell from that context that the argument to RefCell::new()
must be a Box<dyn Trait>
, so despite supplying a Box<E>
, it coerces it to the former type. Rust 可以从该上下文中看出RefCell::new()
的参数必须是Box<dyn Trait>
,因此尽管提供了Box<E>
,但它会将其强制转换为前一种类型。 When you write this on the other hand:另一方面,当您编写此代码时:
let x = Rc::new(RefCell::new(Box::new(e)));
v.push(x); // compile error
Rust first infers that x
of type Rc<RefCell<Box<E>>>
and you can no longer push
it into a vec
of Rc<RefCell<Box<dyn Trait>>>
. Rust 首先推断出x
类型为Rc<RefCell<Box<E>>>
并且您不能再将其push
入Rc<RefCell<Box<dyn Trait>>>
的vec
中。 You can change this by putting an explicit type annotation in your let
binding to tell Rust upfront that you really do want a Rc<RefCell<Box<dyn Trait>>>
:您可以通过在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
}
The important thing to understand here is that E
is not the same as dyn Trait
.这里要理解的重要一点是E
与dyn Trait
不同。 E
is some known concrete implementation of Trait
while dyn Trait
is a trait object with its underlying concrete implementation erased. E
是Trait
的一些已知具体实现,而dyn Trait
是一个特征 object,其底层具体实现已被删除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.