rust 将值强制转换为trait对象的规则是什么?

r8xiu3jd  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(177)

考虑以下Rust代码:

#[derive(Debug, Clone, Copy)]
struct Struct;
trait Trait {}
impl Trait for Struct {}

fn f() {
    // Why does this coerce to the target type (Result<Box<dyn Trait>, ()>)
    let rbdt: Result<Box<dyn Trait>, ()> = Ok(Box::new(Struct));

    // And this coerces to the target type...
    let a = Box::new(Struct);
    let rbdt: Result<Box<dyn Trait>, ()> = Ok(a);

    // But this does not:
    let a = Ok(Box::new(Struct));
    let rbdt: Result<Box<dyn Trait>, ()> = a; // Error: mismatched types
}

字符串
为什么对rbdt的前两个赋值都能正确工作,将值强制转换为目标类型(Result<Box<dyn Trait>, ()>),而第三个却不能?在我看来,在所有三种情况下,赋值的RHS类型都是Result<Box<Struct>, () >,所以令人困惑的是,有些形式工作,而另一些形式导致不匹配的类型错误。
什么时候包含trait对象的类型可以被赋值?这些有文档记录吗?

atmip9wb

atmip9wb1#

这里的基本原则是,编译器会通过在需要的地方默默插入as来将Box<Struct>强制转换为Box<dyn Trait>,但它需要一个地方来真正将代码重写为boxed_struct as BoxedTrait
在第一个例子中,这是可能的:

let rbdt: Result<Box<dyn Trait>, ()> = Ok(Box::new(Struct) as Box<dyn Trait>);

字符串
在第二个:

let a = Box::new(Struct);
let rbdt: Result<Box<dyn Trait>, ()> = Ok(a as Box<dyn Trait>);


但是在第三种情况下,Box<Struct>-as-Box<Trait>强制转换无处可去。当你试图赋值给rbdt时,a的类型已经被确定为Result<Box<Struct>, ()>,此时尝试重新推断类型为更一般的Result<Box<Trait>, ()>已经太晚了。下面是 * 不是 * 一个盒子到盒子的强制转换,所以这是不允许的

let rbdt: Result<Box<dyn Trait>, ()> = a as Result<Box<dyn Trait>, ()>;


Box<Struct>-as-Box<Trait>可以; Type<Box<Struct>>-as-Type<Box<Trait>>,对于任何Type,都不行。

w8biq8rn

w8biq8rn2#

我认为这与其说是强迫,不如说是推理。
在前两种情况下,可以立即推断Result<Box<T>>中的TStruct以外的东西,而在第三种情况下,Box<Struct>已经是一个具体类型,然后与rdbt上的类型注解引入的T = dyn Trait要求相冲突。
此外,我想指出的是,通常不可能将已经存在的值强制转换为不同的类型,特别是更大的大小,其中Box<Struct>Box<dyn Trait>是由于后者是胖指针。

相关问题