Basically, I'm stumped as to how I can actually implGenericEngine given the above associated types and constraints. Any help you guys could provide would be appreciated.
My first impression is that you're trying to be overly generic, and that you're mixing being very generic with being very specific in spots.
These top two probably don't mean what you think. You're introducing a new generic paramter (WidgetA, WidgetB), so they operate just like GenericEngine. You can create an EngineB<WidgetA> for example.
For the commented block, Self is an alias that includes all type parameters after they have been resolved to concrete types. If you want to return a concrete type, you need to either implement for that type
But I'm still not sure this is what you're aiming for, since there can be other implementers of Service that define Widget = WidgetA than ServiceA, and you're type erasing ServiceA. If you're both type erasing something but caring a lot about what the erased type is, you probably have a design flaw.
Thank you both. I'm being generic specifically to find where the stretch points are. I come from a heavy C background, and I'm trying to come to grips with the patterns that make the most sense for more complex systems in Rust.
The specific reason for this particular exercise was ultimately to figure out how to model a system I recently completed in C#, with several entity types (based on a common ancestor), each with a set of services built around it, and an engine created using a builder pattern to include multiple services for a common entity. I wanted to see how (if at all) Rust would catch the user trying to mix services from different entity types in an engine. Both of your responses pointed me in the direction I needed.