Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
902 views
in Technique[技术] by (71.8m points)

rust - How can I downcast from Box<Any> to a trait object type?

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

At some point I want to cast Box<Any> to Box<WidgetTrait>

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

This gives me an error of this kind:

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

What does this really mean?

I've looked at How to fix: value may contain references; add `'static` bound to `T` and did try adding + 'static everywhere.

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

It fixes the compile errors, but fails when I try to unwrap the downcasted box as shown above. And yes, the content of the box is an object that implements WidgetTrait.

Obviously, I am coding in Rust at a level that I don't quite understand, but maybe someone can help me get a better grip on the concepts involved in the above task.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

(I shall ignore the 'static part as it’s comparatively irrelevant for the parts I’m explaining.)

Box<Trait> for a given trait Trait is stored as two pieces of data: a pointer to the actual data in memory and a pointer to the vtable for its type’s implementation of Trait.

From that, you may see that you can only have one level of traityness—if you have a Box<WidgetTrait> and you box it again as Box<Any>, you would only be able to get it out as a Box<WidgetTrait> object. Similarly, if you take a type Widget that implements WidgetTrait and box it in a Box<Any>, you can only get it out as a Widget object, not as a Box<WidgetTrait> object.

Such is the nature of the type IDs being used internally: unlike in a dynamic or VM-based language, the type system is purely a compile-time construct; there is no such thing as the type system at runtime.

The solution, if you really need a solution along these lines (you probably don’t; sticking with just a Box<WidgetTrait> is probably the best way) is to have a trait which also implements what Any does. This is not the simplest thing at present, but can be done. Teepee’s Header trait is an example of how this can work; a Box<Header> object will have the header-transforming methods as well as Any’s .downcast_ref() and so forth.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...