考虑以下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对象的类型可以被赋值?这些有文档记录吗?
2条答案
按热度按时间atmip9wb1#
这里的基本原则是,编译器会通过在需要的地方默默插入
as
来将Box<Struct>
强制转换为Box<dyn Trait>
,但它需要一个地方来真正将代码重写为boxed_struct as BoxedTrait
。在第一个例子中,这是可能的:
字符串
在第二个:
型
但是在第三种情况下,
Box<Struct>
-as-Box<Trait>
强制转换无处可去。当你试图赋值给rbdt
时,a
的类型已经被确定为Result<Box<Struct>, ()>
,此时尝试重新推断类型为更一般的Result<Box<Trait>, ()>
已经太晚了。下面是 * 不是 * 一个盒子到盒子的强制转换,所以这是不允许的型
Box<Struct>
-as-Box<Trait>
可以;Type<Box<Struct>>
-as-Type<Box<Trait>>
,对于任何Type
,都不行。w8biq8rn2#
我认为这与其说是强迫,不如说是推理。
在前两种情况下,可以立即推断
Result<Box<T>>
中的T
是Struct
以外的东西,而在第三种情况下,Box<Struct>
已经是一个具体类型,然后与rdbt
上的类型注解引入的T = dyn Trait
要求相冲突。此外,我想指出的是,通常不可能将已经存在的值强制转换为不同的类型,特别是更大的大小,其中
Box<Struct>
和Box<dyn Trait>
是由于后者是胖指针。