将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)
调用r
到Rc<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/