将 Arc<T> 克隆到 Arc<dyn U>,其中 T 实现 U
Clone Arc<T> into Arc<dyn U> where T implements U
我觉得很奇怪
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;
}
编译,但是
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);
}
错误
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>`
为什么会这样,是否有更短的变体可以从 Arc<Pear>
克隆 Arc<dyn Fruit>
?
这是 Rust 中类型推断工作方式的结果。方法 Arc::clone()
接受一个 &Arc<T>
。编译器需要确定 T
是什么。
在第一个代码片段中,编译器对 Arc::clone(&pear)
的 return 类型没有任何约束,因此它根据传入的参数推断 T
. 参数的类型为 &Arc<Pear>
,因此编译器推断为 T = Pear
。代码片段的最后一行隐式地执行了从 Arc<Pear>
到 Arc<dyn Fruit>
.
的未定大小的强制转换。
在第二个代码片段中,编译器已经知道 Arc::clone(&pear)
所需的 return 类型,因为目标变量包含类型注释。基于此,编译器推断 T = dyn Fruit
并期望类型为 &Arc<dyn Fruit>
的参数。但是,它找到了一个 &Arc<Pear>
,它不能被强制转换为所需的类型,因此编译器会出错。
目前尚未完全说明 Rust 中类型推断如何工作的细节。每当编译器没有推断出正确的类型时,您应该添加一个显式类型提示:
let pear = Arc::new(Pear {});
let cloned_casted: Arc<dyn Fruit> = Arc::<Pear>::clone(&pear);
这样一来,编译器就不需要推断 T
是什么,并且代码会按预期工作。
有时您还可以让编译器推断出正确的类型。这也有效:
let cloned_casted: Arc<dyn Fruit> = Arc::clone(&pear) as _;
编译器可以将 _
推断为 Arc<dyn Fruit>
,但它不再知道你从 从 转换什么类型,所以它需要以与第一个代码片段中相同的方式推断该类型。
另请参阅:
除了Sven Marnach的变体,我们还可以做
let cloned_casted: Arc<dyn Fruit> = pear.clone();
我觉得很奇怪
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;
}
编译,但是
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);
}
错误
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>`
为什么会这样,是否有更短的变体可以从 Arc<Pear>
克隆 Arc<dyn Fruit>
?
这是 Rust 中类型推断工作方式的结果。方法 Arc::clone()
接受一个 &Arc<T>
。编译器需要确定 T
是什么。
在第一个代码片段中,编译器对 Arc::clone(&pear)
的 return 类型没有任何约束,因此它根据传入的参数推断 T
. 参数的类型为 &Arc<Pear>
,因此编译器推断为 T = Pear
。代码片段的最后一行隐式地执行了从 Arc<Pear>
到 Arc<dyn Fruit>
.
在第二个代码片段中,编译器已经知道 Arc::clone(&pear)
所需的 return 类型,因为目标变量包含类型注释。基于此,编译器推断 T = dyn Fruit
并期望类型为 &Arc<dyn Fruit>
的参数。但是,它找到了一个 &Arc<Pear>
,它不能被强制转换为所需的类型,因此编译器会出错。
目前尚未完全说明 Rust 中类型推断如何工作的细节。每当编译器没有推断出正确的类型时,您应该添加一个显式类型提示:
let pear = Arc::new(Pear {});
let cloned_casted: Arc<dyn Fruit> = Arc::<Pear>::clone(&pear);
这样一来,编译器就不需要推断 T
是什么,并且代码会按预期工作。
有时您还可以让编译器推断出正确的类型。这也有效:
let cloned_casted: Arc<dyn Fruit> = Arc::clone(&pear) as _;
编译器可以将 _
推断为 Arc<dyn Fruit>
,但它不再知道你从 从 转换什么类型,所以它需要以与第一个代码片段中相同的方式推断该类型。
另请参阅:
除了Sven Marnach的变体,我们还可以做
let cloned_casted: Arc<dyn Fruit> = pear.clone();