为什么不能用let _创建特征对象:Arc< dyn Trait> = value.into()?

为什么不能用let _创建特征对象:Arc< dyn Trait> = value.into()?

问题描述:

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
}

结果:

error[E0277]: the trait bound `std::sync::Arc<dyn Trait>: std::convert::From<TraitImpl>` is not satisfied
  --> src/main.rs:10:35
   |
10 |     let _: Arc<dyn Trait> = value.into();       // doesn't compile
   |                                   ^^^^ the trait `std::convert::From<TraitImpl>` is not implemented for `std::sync::Arc<dyn Trait>`
   |
   = help: the following implementations were found:
             <std::sync::Arc<T> as std::convert::From<T>>
             <std::sync::Arc<T> as std::convert::From<std::boxed::Box<T>>>
             <std::sync::Arc<[T]> as std::convert::From<&[T]>>
             <std::sync::Arc<[T]> as std::convert::From<std::vec::Vec<T>>>
           and 8 others
   = note: required because of the requirements on the impl of `std::convert::Into<std::sync::Arc<dyn Trait>>` for `TraitImpl`

(游乐场 )

为什么Arc::new(value)可以编译,而value.into()不可以编译?我不明白为什么 Arc<T>::new() 满意,而 From<T>::from 不是.

Why does Arc::new(value) compile but not value.into()? I don't understand why Arc<T>::new() is satisfied while From<T>::from isn't.

impl<T> Arc<T> {
    pub fn new(data: T) -> Arc<T>
}

impl<T> From<T> for Arc<T> {
    fn from(t: T) -> Arc<T>
}

您的两行有根本的区别.第一个:

There is a fundamental difference in your two lines. The first one:

let _: Arc<dyn Trait> = Arc::new(value);

该模式对于Arc::new()的分辨率并不重要,因为它的定义如您所述:

The pattern is not important for the resolution of Arc::new(), since it is defined as you noted:

impl<T> Arc<T> {
    pub fn new(data: T) -> Arc<T>
}

因此从value的类型TraitImpl推导类型T,并创建了Arc<TraitImpl>. 然后,将这种类型隐式地对大小Arc<dyn Trait>进行无限制强制,然后所有编译就可以了.

So the type T is deduced from the type of value that is TraitImpl, and an Arc<TraitImpl> is created. Then this type is implicitly unsized-coerced to that Arc<dyn Trait> and all compiles fine.

但是第二行比较棘手:

let _: Arc<dyn Trait> = value.into();

由于TraitImpl中没有into函数,因此编译器在范围内搜索任何特征并找到Into<T>::into(),其定义为:

Since there is not an into function in TraitImpl the compiler searches any trait in scope and finds Into<T>::into(), that is defined as:

pub trait Into<T> {
    fn into(self) -> T;
}

现在,编译器想知道T是什么类型.由于它是函数的返回,因此它猜测TArc<dyn Trait>.现在,Into的唯一有趣的实现是根据From:

Now the compiler wonders what type would that T be. Since it is the return of the function, it guesses that T is Arc<dyn Trait>. Now the only interesting implementation of Into is in terms of From:

impl<X, T> Into<T> for X where
    T: From<X>

此处XTraitImpl,而TArc<dyn Trait>.如果您查看ArcFrom的暗示,则其中包括很多,但没有一个适用.这是最相似的:

Here X is TraitImpl and T is Arc<dyn Trait>. If you look at the impls of Arc for From, it includes a lot of them, but none that applies. This is the most similar:

impl<T> From<T> for Arc<T>

然后,编译器将显示一些失败的候选对象并发出错误.

Then, the compiler shows a few of the failing candidates and emits an error.

TL; DR; 实际上是要进行两次转换:从TraitImplArc<TraitImpl>,然后从Arc<TraitImpl>Arc<dyn Trait>.但是您不能一次执行两个操作,编译器必须以某种方式阐明中间类型.

The TL;DR; is that you actually want to do two conversions: from TraitImpl to Arc<TraitImpl> and then from Arc<TraitImpl> to Arc<dyn Trait>. But you cannot do both in a single coertion, the compiler must have the intermediate type spelled out somehow.