DEV Community

Cover image for Callbacks, Trait Objects & Associated Types, Oh My!

Callbacks, Trait Objects & Associated Types, Oh My!

Ben Lovy on September 03, 2019

Last week, I promised a dive into Rust procedural macros as I work to design a DSL for my Widget UI building-block trait. What I've learned is not...
Collapse
 
jeikabu profile image
jeikabu

I usually see PhatomData used with raw pointers like in the nomicon link, but I guess it could hold the type like that.

Text isn't actually using the type, so couldn't it just not be parameterized?:

impl Widget for Text {
    type MSG = String; //or whatever
//...
}

Maybe I didn't read everything else closely enough.

Collapse
 
deciduously profile image
Ben Lovy

Yeah, that's what's giving me pause - this use case bears little to no resemblance to the example uses given.

I can't just assign it to some random type, even though I don't use it, because in order to include it in a parent widget it must use the same MSG type as every other widget in the tree. The toplevel struct, WindowEngine, demands a member field of type Box<dyn Widget<MSG = T>>, and the MountedWidget<T> struct also gets parameterized with this type. The compiler complains when I attempt to add a child Widget<MSG = String> to a parent of type MountedWidget<FiveDiceMessage>, as it should. All the types need to match, even though this particular child will never produce an actual value containing that type.

Collapse
 
jeikabu profile image
jeikabu

Ah, I see

Thread Thread
 
deciduously profile image
Ben Lovy

It's posible it all just means I need to refactor. Ideally I'd like to create a separate Clickable trait, but I'm not sure how to check for a trait at runtime. I'd like all of the children to be Widgets but only some to be Clickable, and somehow be able to traverse the tree and use either where appropriate, but haven't figured out what that looks like. Is there a way to "detect" another trait implementation after a trait object has been created? My gut says no, that contradicts what I know about trait objects.

Thread Thread
 
jeikabu profile image
jeikabu

Just realized I've yet looked at how to do that. Seems std::any::Any is the current solution.

But you're right, I suspect there's more Rust-y way to implement things.

Thread Thread
 
deciduously profile image
Ben Lovy • Edited

Yeah, I came across that too and played with it a little, but never found anything that didn't feel similarly kludgy. I don't really want to forfeit type checking, seems like a deeper structural change is likely in order.