克隆弧 <T>进入 Arc<dyn U>其中 T 实现 U [英] Clone Arc<T> into Arc<dyn U> where T implements U

查看:20
本文介绍了克隆弧 <T>进入 Arc<dyn U>其中 T 实现 U的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

I find pretty weird that

use std::sync::Arc;

trait Fruit {}
struct Pear {}
impl Fruit for Pear {}

fn main() {
    let pear = Arc::new(Pear {});
    let cloned = Arc::clone(&pear);
    let cloned_casted: Arc<dyn Fruit> = cloned;
}

compiles, but

use std::sync::Arc;

trait Fruit {}
struct Pear {}
impl Fruit for Pear {}

fn main() {
    let pear = Arc::new(Pear {});
    let cloned_casted: Arc<dyn Fruit> = Arc::clone(&pear);
}

errors out with

error[E0308]: mismatched types
 --> main.rs:9:52
  |
9 |     let cloned_casted: Arc<dyn Fruit> = Arc::clone(&pear);
  |                                                    ^^^^^ expected trait object `dyn Fruit`, found struct `Pear`
  |
  = note: expected reference `&Arc<dyn Fruit>`
             found reference `&Arc<Pear>`

Why is so, and is there a shorter variant to clone Arc<dyn Fruit> from Arc<Pear>?

解决方案

This is a result of how type inference works in Rust. The method Arc::clone() accepts an &Arc<T>. The compiler needs to determine what T is.

In the first code snippet, the compiler doesn't have any constraints for the return type of Arc::clone(&pear), so it infers T based on the argument that is passed in. The argument has type &Arc<Pear>, so the compiler infers that T = Pear. The last line in the code snippet implicitly performs an unsized coercion from Arc<Pear> to Arc<dyn Fruit>.

In the second code snippet, the compiler already knows the desired return type of Arc::clone(&pear), since the target variable includes a type annotation. Based on that, the compiler infers T = dyn Fruit and expects an argument of type &Arc<dyn Fruit>. However, it finds an &Arc<Pear> instead, which can't be coerced into the desired type, so the compiler errors out.

The details how type inference works in Rust are not fully specified at this time. Whenever the compiler does not infer the correct type, you should add an explicit type hint:

let pear = Arc::new(Pear {});
let cloned_casted: Arc<dyn Fruit> = Arc::<Pear>::clone(&pear);

This way, the compiler doesn't need to infer what T is, and the code works as expected.

Sometimes you can also nudge the compiler to infer the correct type. This works as well:

let cloned_casted: Arc<dyn Fruit> = Arc::clone(&pear) as _;

The compiler can infer _ to mean Arc<dyn Fruit>, but it doesn't know anymore what type you are casting from, so it needs to infer that type the same way it had to in the first code snippet.

See also:

这篇关于克隆弧 &lt;T&gt;进入 Arc&lt;dyn U&gt;其中 T 实现 U的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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