Downcasting和Box <any> </any>

时间:2014-08-11 15:04:38

标签: rust downcast

pub struct WidgetWrap {
    // ...
    widget: RefCell<Box<Any>>,
}

在某些时候,我想将Box<Any>投射到Box<WidgetTrait>

let mut cell = widget.borrow_mut();
let w = cell.downcast_mut::<Box<WidgetTrait>>();

这给我一个错误:

error: instantiating a type parameter with an incompatible type
`Box<WidgetTrait>`, which does not fulfill `'static` [E0144]

这究竟意味着什么?

我已查看How to fix: value may contain references; add `'static` bound to `T`并尝试在任何地方添加+ 'static

pub struct WidgetWrap {
    // ...
    widget: RefCell<Box<Any + 'static>>,
}
let mut cell = widget.borrow_mut();
let w = cell.downcast_mut::<Box<WidgetTrait + 'static>>();

它修复了编译错误,但是当我尝试打开如下所示的downcasrap框时失败了。是的,该框的内容是一个实现WidgetTrait的对象。

显然,我在Rust编写的程度是我不太了解的,但也许有人可以帮助我更好地掌握上述任务所涉及的概念。

2 个答案:

答案 0 :(得分:11)

(我将忽略'static部分,因为它与我正在解释的部分相对无关。)

给定特征Box<Trait>

Trait存储为两个数据:指向内存中实际数据的指针和指向vtable的指针,用于其类型的Trait实现。

从那以后,您可能会发现只有一个级别的特权 - 如果您有一个Box<WidgetTrait>并且再次将其设为Box<Any>,那么您只能将其作为一个Box<WidgetTrait>个对象。同样,如果您使用实现Widget的类型WidgetTrait并将其设置为Box<Any>,则只能将其作为Widget对象获取,而不是Box<WidgetTrait> 1}}对象。

这是内部使用的类型ID的本质:与基于动态或基于VM的语言不同,类型系统纯粹是编译时构造; 在运行时没有类型系统

解决方案,如果你真的需要这些方面的解决方案(你可能不这样做;只坚持Box<WidgetTrait>可能是最好的方法)就是要有一个特性也实现了Any的功能。这不是目前最简单的事情,但可以做到。 Teepee’s Header trait是一个如何运作的例子; Box<Header>对象将包含标头转换方法以及Any的{​​{1}}等等。

答案 1 :(得分:1)

原始代码至少在Rust 1.25中工作;据推测,编译器中存在一个已修复的错误或限制:

use std::any::Any;
use std::cell::RefCell;

trait WidgetTrait {}

fn example(widget: RefCell<Box<Any>>) {
    let mut cell = widget.borrow_mut();
    let w = cell.downcast_mut::<Box<WidgetTrait>>();
}

fn main() {}