Rust 为什么不能借用装箱结构作为特征?

Rust 为什么不能借用装箱结构作为特征?,rust,traits,Rust,Traits,给定一个实现trait T的结构,为什么Box不实现借用 我本来希望编译的以下代码没有: 性状T{} 结构S{} S{}的impl T fn f1s:&S->&dyn T{ s } fn f2s:&Box->&dyn T{ 标准::借用::借用::借用 } 为什么f1编译而f2不编译?从&S到&dyn T的转换在第一种情况下完成,而不是在第二种情况下完成 &Box不直接等于Box,这就是它不直接编译的原因 您可以通过以下方式相对轻松地解决此问题: use std::ops::Deref; tra

给定一个实现trait T的结构,为什么Box不实现借用

我本来希望编译的以下代码没有:

性状T{} 结构S{} S{}的impl T fn f1s:&S->&dyn T{ s } fn f2s:&Box->&dyn T{ 标准::借用::借用::借用 } 为什么f1编译而f2不编译?从&S到&dyn T的转换在第一种情况下完成,而不是在第二种情况下完成

&Box不直接等于Box,这就是它不直接编译的原因

您可以通过以下方式相对轻松地解决此问题:

use std::ops::Deref;
trait T{}
struct S{}
impl T for S{}

fn f1(s : &S) -> &(dyn T) {
    s
}

fn f2(s : &Box<S>) -> &(dyn T) {
    s.deref()
}
Deref的特点是更易于阅读

对deref的调用在&self上运行,因此使用&Box就足以调用它。它只返回&S,因为它实现了T类型签出。

&Box不直接等于Box,这就是它不直接编译的原因

您可以通过以下方式相对轻松地解决此问题:

use std::ops::Deref;
trait T{}
struct S{}
impl T for S{}

fn f1(s : &S) -> &(dyn T) {
    s
}

fn f2(s : &Box<S>) -> &(dyn T) {
    s.deref()
}
Deref的特点是更易于阅读


对deref的调用在&self上运行,因此使用&Box就足以调用它。它只返回&S,因为它实现了类型签出。

这与类型推断和类型强制的工作方式有关。借用特征的参数是借用值的类型,类型检查器需要知道它是什么

如果你只是写:

std::borrow::Borrow::borrow(s)
然后,将根据周围代码推断出借用中的类型B。在您的例子中,它被推断为dyn T,因为这是返回值。然而,DYNT是与S完全不同的类型,因此它不进行类型检查

一旦类型检查器知道返回的值属于&S类型,它就可以将其强制为&dyn T,但您需要为其提供该信息:

fn f2(s: &Box<S>) -> &dyn T {
    let s: &S = std::borrow::Borrow::borrow(s);
    s
}
或者,更简洁地说:

fn f2(s: &Box<S>) -> &dyn T {
    std::borrow::Borrow::<S>::borrow(s)
}

之所以有效,是因为Deref使用关联的类型而不是类型参数。类型检查器可以很容易地推断::Target,因为每个类型只能有一个Deref实现,并且关联的目标类型是唯一确定的。借用是不同的,因为Box可以实现借用、借用、借用,。。。因此,您必须更明确地说明您想要哪种实现。

这与类型推断和类型强制的工作方式有关。借用特征的参数是借用值的类型,类型检查器需要知道它是什么

如果你只是写:

std::borrow::Borrow::borrow(s)
然后,将根据周围代码推断出借用中的类型B。在您的例子中,它被推断为dyn T,因为这是返回值。然而,DYNT是与S完全不同的类型,因此它不进行类型检查

一旦类型检查器知道返回的值属于&S类型,它就可以将其强制为&dyn T,但您需要为其提供该信息:

fn f2(s: &Box<S>) -> &dyn T {
    let s: &S = std::borrow::Borrow::borrow(s);
    s
}
或者,更简洁地说:

fn f2(s: &Box<S>) -> &dyn T {
    std::borrow::Borrow::<S>::borrow(s)
}
之所以有效,是因为Deref使用关联的类型而不是类型参数。类型检查器可以很容易地推断::Target,因为每个类型只能有一个Deref实现,并且关联的目标类型是唯一确定的。借用是不同的,因为Box可以实现借用、借用、借用,。。。因此,您必须更明确地说明您想要的实现。

&Box并不直接等于Box。但是,在这两种情况下,&Box::borow的类型不都是&S吗?&Box并不直接等于Box。但是在这两种情况下,&Box::borow的类型不是都是&S吗?