Joh*_*ica 3 generics traits rust trait-objects
use std::sync::Arc;
trait Trait {}
struct TraitImpl {}
impl Trait for TraitImpl {}
fn main() {
let value = TraitImpl {};
let _: Arc<dyn Trait> = Arc::new(value); // compiles
let _: Arc<dyn Trait> = value.into(); // doesn't compile
}
Run Code Online (Sandbox Code Playgroud)
结果
use std::sync::Arc;
trait Trait {}
struct TraitImpl {}
impl Trait for TraitImpl {}
fn main() {
let value = TraitImpl {};
let _: Arc<dyn Trait> = Arc::new(value); // compiles
let _: Arc<dyn Trait> = value.into(); // doesn't compile
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
为什么Arc::new(value)编译但不编译value.into()?我不明白为什么Arc<T>::new()满意而From<T>::from不是。
impl<T> Arc<T> {
pub fn new(data: T) -> Arc<T>
}
Run Code Online (Sandbox Code Playgroud)
impl<T> From<T> for Arc<T> {
fn from(t: T) -> Arc<T>
}
Run Code Online (Sandbox Code Playgroud)
你的两条线有根本区别。第一个:
let _: Arc<dyn Trait> = Arc::new(value);
Run Code Online (Sandbox Code Playgroud)
该模式对于 的分辨率并不重要Arc::new(),因为它的定义正如您所指出的:
impl<T> Arc<T> {
pub fn new(data: T) -> Arc<T>
}
Run Code Online (Sandbox Code Playgroud)
因此,类型T从类型推断value是TraitImpl和Arc<TraitImpl>创建。然后这种类型被隐式地强制转换为该类型,Arc<dyn Trait>并且所有编译都很好。
但第二行更诡异:
let _: Arc<dyn Trait> = value.into();
Run Code Online (Sandbox Code Playgroud)
由于编译器中没有into函数在TraitImpl范围内搜索任何特征并找到Into<T>::into(),因此定义为:
pub trait Into<T> {
fn into(self) -> T;
}
Run Code Online (Sandbox Code Playgroud)
现在编译器想知道那T是什么类型。既然是函数的返回,它猜测T是Arc<dyn Trait>。现在唯一有趣的实现Into是From:
impl<X, T> Into<T> for X where
T: From<X>
Run Code Online (Sandbox Code Playgroud)
这里X是TraitImpl并且T是Arc<dyn Trait>。如果您查看 for 的 Arc实现From,它包含很多实现,但没有一个适用。这是最相似的:
impl<T> From<T> for Arc<T>
Run Code Online (Sandbox Code Playgroud)
然后,编译器显示一些失败的候选者并发出错误。
该TL; DR; 是您实际上想要进行两次转换: from TraitImpltoArc<TraitImpl>和 from Arc<TraitImpl>to Arc<dyn Trait>。但是你不能在一个 coertion 中同时做这两个,编译器必须以某种方式拼出中间类型。