// These are simplifications of the tower traits by the same name: pub trait Service { type Response; } pub trait Layer { type Service; } // Any type will do here: pub struct Req; pub struct Res; // This is encoding a trait alias. pub trait ParticularService: Service { } impl ParticularService for T where T: Service, { } // This is also a trait alias. // The weird = bound is there so that users of the trait do not // need to repeat the bounds. See https://github.com/rust-lang/rust/issues/20671 // for context, and in particular the workaround in: // https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828 pub trait ParticularServiceLayer: Layer>::Service> { type Service: ParticularService; } impl ParticularServiceLayer for T where T: Layer, T::Service: ParticularService, { type Service = T::Service; } // These are types that implement the traits that the trait aliases refer to. // They should also implement the alias traits due to the blanket impls. struct ALayer(C); impl Layer for ALayer { type Service = AService; } struct AService; impl Service for AService { // However, AService does _not_ meet the blanket implementation, // since its Response type is bool, not Res as it should be. type Response = bool; } // This is a wrapper type around ALayer that uses the trait alias // as a way to communicate the requirements of the provided types. struct Client(C); // The method and the free-standing function below both have the same bounds. impl Client where ALayer: ParticularServiceLayer, { fn check(&self) {} } fn check(_: C) where ALayer: ParticularServiceLayer {} // But, they give very different error messages. fn main() { // This gives a very poor error message that does nothing to point the user // at the underlying cause of why the types involved do not meet the bounds. Client(()).check(); //~ ERROR E0599 // This gives a good(ish) error message that points the user at _why_ the // bound isn't met, and thus how they might fix it. check(()); //~ ERROR E0271 }