rust - 将Rc <dyn Trait>作为函数参数传递时出错

标签 rust

Rc<dyn Trait>作为函数参数传递时,我面临一些奇怪的行为。以下代码演示了该问题。

use std::rc::Rc;

trait Trait {}

struct Struct {}

impl Trait for Struct {}

fn function(_t: Rc<dyn Trait>) {}

fn main() {
    let n = Rc::new(Struct {});

    // ok
    let r = Rc::clone(&n);
    function(r);

    // error, why?
    // function(Rc::clone(&n));
}
如果我将Rc存储在一个临时变量中,则一切正常。但是,如果我尝试直接在函数调用中调用Rc::clone,则会收到以下错误。
   |
19 |     function(Rc::clone(&n));
   |                        ^^ expected trait object `dyn Trait`, found struct `Struct`
   |
   = note: expected reference `&std::rc::Rc<dyn Trait>`
              found reference `&std::rc::Rc<Struct>`
Struct实现Trait。为什么会出现此错误?

最佳答案

这基本上只是类型推断规则中的一个小问题。为了调用Rc::clone(&n),编译器必须知道Rc的类型参数是什么。

let r = Rc::clone(&n);
function(r);
在第一行,编译器看到Rc::clone被调用了&Rc<Struct>类型的参数。它可以自由选择r的类型,因此可以推断出被调用的函数应该是Rc::<Struct>::clone,而r也是Rc<Struct>。移至下一行,仅将coerces function(r)调用rRc<dyn Trait>
function(Rc::clone(&n));
在这里,编译器再次必须为Rc选择类型参数,但它没有完全的自由:它必须选择可以传递给function的东西。因此,它假定type参数为dyn Trait,因为Rc<dyn Trait>function所期望的。
但是,您不能调用Rc::<dyn Trait>::clone(&n),因为Rc<Struct>可以强制转换为Rc<dyn Trait>coercions are not transitive through referencing(您不能将&Rc<Struct>强制转换为&Rc<dyn Trait>)。因此,不能在Rc::clone(...)调用内进行强制转换。
您可以通过使用turbofish将type参数指定为Struct来编译单行版本:
function(Rc::<Struct>::clone(&n));
或通过向编译器暗示它不应从其位置作为function的参数来推断类型,方法是添加一个显式的强制转换:
function(Rc::clone(&n) as _);
n.clone()也可以工作,因为method resolution procedure for . 对类型参数毫无疑问:它将始终找到Rc::<Struct>::clone,因为自动取消引用仅查看接收者的类型(n的类型),而不关心表达式的上下文。

关于rust - 将Rc <dyn Trait>作为函数参数传递时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63893847/

相关文章:

rust - 为什么初始化向量的向量 (Vec<Vec<T>>) 需要 T 而不是 Vec<T>?

rust - 为什么我们可以在同一范围内对同一数据有多个可变引用?

rust - 是否可以将包含闭包的 Rust 结构存储在不同的结构中?

rust - 调用一个函数,该函数使用不同的闭包进行两次闭包

vector - 如何将盒子向量转换为引用向量?

rust - 如何仅在 Option 为 None 时有条件地执行代码?

generics - 如何迭代实现 Index 和 IntoIterator 的通用集合的索引?

rust - 我怎样才能让编译器警告我标记为 pub 的未使用代码?

rust - 编译完成后可以执行任务吗?

rust - 如何使用跟踪订阅者设置自定义时间戳格式?