简体   繁体   English

除非我使用临时变量,否则为什么我不能推入 Vec 的 dyn Trait?

[英]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>>>并且您不能再将其pushRc<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
}

playground 操场

The important thing to understand here is that E is not the same as dyn Trait .这里要理解的重要一点是Edyn Trait不同。 E is some known concrete implementation of Trait while dyn Trait is a trait object with its underlying concrete implementation erased. ETrait的一些已知具体实现,而dyn Trait是一个特征 object,其底层具体实现已被删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何克隆 Vec <Box<dyn Trait> &gt;? - How can I clone a Vec<Box<dyn Trait>>? 为什么我不能用 let _: Arc 创建一个特征 object<dyn trait> = value.into()?</dyn> - Why can't I create a trait object with let _: Arc<dyn Trait> = value.into()? 为什么我不能移出 Vec 的索引<Rc<dyn T> &gt;? - Why can't I move out of index of Vec<Rc<dyn T>>? 为什么我不能在 Rc 中使用这个闭包<dyn Fn()> ? - Why can't I use this closure inside a Rc<dyn Fn()>? `Box` 是否掩盖了特征界限? 在这种情况下,为什么我可以将 `dyn FnOnce()` 分配给 `dyn Fn()`? - Does `Box` obscure trait bounds? Why can i assign `dyn FnOnce()` to `dyn Fn()` in this case? 为什么不能将 `&amp;(?Sized + Trait)` 转换为 `&amp;dyn Trait`? - Why can't `&(?Sized + Trait)` be cast to `&dyn Trait`? 为Vec添加实现后,为什么Rust编译器不使用预期的trait实现 <T> ? - Why does the Rust compiler not use the expected trait implementation once I add an implementation for Vec<T>? 如何结合 Vec 的特征实现<t>以及 Vec&lt;&amp;T&gt;</t> - How can I combine implementations of a trait for Vec<T> as well as Vec<&T> 如何克隆 Vec <Box<dyn SomeTrait> &gt; 在一个物体上? - How can I clone a Vec<Box<dyn SomeTrait>> on an object? 如何将具体的静态分派的“T: Trait”转换为动态分派的“dyn Trait”? - How do I convert a concrete, statically dispatched `T: Trait` to a dynamically dispatched `dyn Trait`?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM