My first project for learning Rust is a highly dynamic layout engine using termion. The idea is to have a tree of handlers implementing different traits. Unfortunately I hit one of the dark corners of Rust because each handler needs a link to its parent. Because all handlers are boxed, a plain ptr (*const Handler) can safely be used. To initialize the parent ptr I use a Dummy:
impl Dummy {
pub fn new() -> Box {
let t = Dummy {};
Box::new(t) as Box
}
}
impl Widget for Dummy {
fn init(&mut self){ panic!(Dummy called!); }
// ...
}[/code]
Since I need a small number of other handlers beside Widget I would like to have a generic Dummy but cannot figure out how to implement this. I could not find an example, may be because I'm not yet familiar enough with Rust. Any help or pointers to code are appreciated!
I don't really get your problem, but for your Idea with using a plain ptr:
This seems safe at first but allows for two things that are not rusty:
A Box go out of scope before it's child -> Dangeling pointer
A owned Box may be modified while at the same time a (const) reference to it exists.
Normally Rust would not compile a program where this is possible.
So I recommend using Rc<RefCell<Widget>> instead of Box<Widget>. Use a weak pointer to that Rc-Box (instead of the const* you had in mind) within the child widgets as parent pointer.
Rc means ref-counted, doesn't it? That means an unnecessary overhead because the raw ptr will never (!) be borrowed. The question is how to make an generic Dummy which works with different traits, something like Dummy::new() where T is Widget, a Container for Widgets or others. Of course, for each trait an impl is needed but the Interface is coherent. Here is how I want to use the dummy:
The ?Sized bound is necessary because trait object types like Widget do not implement the built-in trait Sized, because they do not have a statically determined size.
This code in general suggests you're thinking about this in terms of "object oriented / inheritance" mechanism. A Dummy<T> is not a subclass of T; remember that T is a type and not a trait and could be, for example, u32. How would you go from a Dummy<u32> to a Box<u32>, for example? You can't because you don't have any u32. The type system doesn't distinguish between trait object types and other types.
There might be some very hacky ways get the behavior you want (restrict T to a trait object type & perform the cast) but in my opinion you are much better off just writing Box::new(Dummy::new()) as Box<Widget>.