将 aRc<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));
}
Run Code Online (Sandbox Code Playgroud)
如果我将 存储Rc在一个临时变量中,则一切正常。但是,如果我尝试Rc::clone在函数调用中直接调用,则会出现以下错误。
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));
}
Run Code Online (Sandbox Code Playgroud)
Struct实施Trait. 为什么我会收到这个错误?
这基本上只是类型推断规则的一个皱纹。为了调用Rc::clone(&n),编译器必须知道 的类型参数Rc是什么。
let r = Rc::clone(&n);
function(r);
Run Code Online (Sandbox Code Playgroud)
在第一行,编译器看到它Rc::clone被一个类型为的参数调用&Rc<Struct>。它可以自由选择 for 的类型r,因此它推断被调用的函数应该是Rc::<Struct>::clone并且r也是Rc<Struct>。移动到下一行,调用function(r)只是强制 r到Rc<dyn Trait>.
function(Rc::clone(&n));
Run Code Online (Sandbox Code Playgroud)
这里编译器再次必须为 选择一个类型参数Rc,但它没有完全的自由:它必须选择可以传递给 的东西function。所以它假设类型参数是dyn Trait,因为这Rc<dyn Trait>是function期望的。
但是,您不能调用Rc::<dyn Trait>::clone(&n),因为 whileRc<Struct>可以被强制为Rc<dyn Trait>,强制不能通过引用传递(您不能将 a 强制&Rc<Struct>为&Rc<dyn Trait>)。所以强制不能在Rc::clone(...)调用中发生。
您可以通过将类型参数指定为Struct使用 turbofish来编译单行版本:
function(Rc::<Struct>::clone(&n));
Run Code Online (Sandbox Code Playgroud)
或者通过function添加显式强制转换来暗示编译器它不应从其作为 的参数的位置推断类型:
function(Rc::clone(&n) as _);
Run Code Online (Sandbox Code Playgroud)
n.clone()也可以工作,因为for.的方法解析过程对类型参数没有任何疑问:它总是会发现,Rc::<Struct>::clone因为自动取消引用只查看接收器类型( 的类型n)而不关心表达式的上下文。
| 归档时间: |
|
| 查看次数: |
469 次 |
| 最近记录: |