传递 Rc<dyn Trait> 时出错作为函数参数 [英] Error when passing Rc<dyn Trait> as a function argument

查看:54
本文介绍了传递 Rc<dyn Trait> 时出错作为函数参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Rc 作为函数参数传递时,我遇到了一些奇怪的行为.下面的代码演示了这个问题.

I'm facing some strange behavior when passing an Rc<dyn Trait> as a function argument. The following code demonstrates the problem.

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,则会出现以下错误.

If I store the Rc in a temporary variable, everything works fine. But if I try to call Rc::clone directly within the function call, I get the following error.

   |
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.为什么会出现此错误?

Struct implements Trait. Why do I get this error?

推荐答案

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

This is basically just a wrinkle in the type inference rules. In order to call Rc::clone(&n), the compiler has to know what the type parameter of Rc is.

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

在第一行,编译器看到 Rc::clone 是用 &Rc 类型的参数调用的.它可以为r自由选择一个类型,因此它推断被调用的函数应该是Rc::<Struct>::cloner 也是 Rc.移动到下一行,调用 function(r) 只是 强制 rRc.

At the first line, the compiler sees that Rc::clone is called with an argument of type &Rc<Struct>. It can freely pick a type for r, so it infers that the function being called should be Rc::<Struct>::clone and r is also Rc<Struct>. Moving to the next line, calling function(r) just coerces r to Rc<dyn Trait>.

function(Rc::clone(&n));

这里编译器再次必须为 Rc 选择一个类型参数,但它没有完全的自由:它必须选择可以传递给 function 的东西.所以它假设类型参数是 dyn Trait,因为 Rcfunction 所期望的.

Here the compiler again has to pick a type parameter for Rc, but it doesn't have total freedom: it has to pick something that can be passed to function. So it assumes the type parameter is dyn Trait, since Rc<dyn Trait> is what function expects.

但是,您不能调用 Rc::<dyn Trait>::clone(&n),因为 Rc 可以被强制为 Rc, 强制不能通过引用传递(您不能强制&Rc;&Rc).所以强制不能在 Rc::clone(...) 调用中发生.

However, you cannot call Rc::<dyn Trait>::clone(&n), because while Rc<Struct> can be coerced to Rc<dyn Trait>, coercions are not transitive through referencing (you can't coerce a &Rc<Struct> to &Rc<dyn Trait>). So coercion cannot take place inside the Rc::clone(...) call.

您可以通过使用 turbofish 将类型参数指定为 Struct 来编译单行版本:

You can make the one-line version compile by specifying the type argument as Struct using a turbofish:

function(Rc::<Struct>::clone(&n));

或者通过添加显式强制转换来暗示编译器它不应该从其作为 function 的参数的位置推断类型:

or by hinting to the compiler that it should not infer the type from its position as the argument of function, by adding an explicit cast:

function(Rc::clone(&n) as _);

n.clone() 也有效,因为 的方法解析过程. 没有留下关于类型参数的怀疑空间:它总是会找到 Rc::<Struct>::clone 因为自动解引用只查看接收器类型(n) 并且不关心表达式的上下文.

n.clone() also works because the method resolution procedure for . leaves no room for doubt about the type parameter: it will always find Rc::<Struct>::clone because auto-dereferencing only looks at the receiver type (the type of n) and does not care about the expression's context.

这篇关于传递 Rc&lt;dyn Trait&gt; 时出错作为函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆