The where bound on BufferUdpSocketContext is causing problems. Thanks to the lack of implied bounds, I have to propagate the where bound to call callers/sub-traits. In my codebase, this is 90 different code locations.
My question is: Is there some way to hack around this that approximates the same behavior but without having the bound be "viral" in this way? I'm happy to restructure the traits if need be, but at a minimum, I need:
One trait which does not take a B: BufferMut parameter, and has an associated Socket type
One trait which does take a B: BufferMut parameter, and has an associated Socket type (maybe its own, or maybe <Self as UdpSocketContext>::Socket) with a BufferUdpSocket<B> bound
The two Socket types in the two contexts are the same (ie, I can use them interchangeably in code and rustc will know that that's OK)
Feel free to try that, I’d be curious how good or bad rustc handles this approach
In case your actual BufferUdpSocketContext trait doesn’t already have a generic impl like
impl<T: ?Sized, B> BufferUdpSocketContext<B> for T
where
B: BufferMut,
T: UdpSocketContext,
T::Socket: BufferUdpSocket<B>,
{
type TheSocketType = T::Socket;
}
(e.g. because there are extra methods), you can spare the boilerplate of defining this TheSocketType manually for every impl, with an additional generically implemented helper trait, and make that a supertrait of BufferUdpSocketContext.
It’s called TheSocketType with the intention of not being used (because it’s supposed to be the same as Socket) but not causing ambiguities. Maybe something like “_Socket” would be a better name.