传递 Rc<dyn Trait> 时出错作为函数参数 [英] Error when passing Rc<dyn Trait> as a function argument
问题描述
将 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>::clone
和r
也是 Rc
.移动到下一行,调用 function(r)
只是 强制 r
到 Rc
.
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
,因为 Rc
是 function
所期望的.
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<dyn Trait> 时出错作为函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!