DRYing type parameter constraints

I got a codebase where I got lots of complex type parameter constraints. Things like:

fn foo<T>(x: T)
    where T: Display + Debug + Send + Sync + Clone + 'static

I find this kind of annoying. So I came up with this way to DRY the constraints:

use std::fmt::{Display, Debug};

trait TheUsual: Display + Debug + Send + Sync + Clone + 'static {}
impl<T: Display + Debug + Send + Sync + Clone + 'static> TheUsual for T {}

fn foo(x: impl TheUsual) {
    println!("{} {:?}", x, x);

fn main() {

This seems to work as far as I can see. Is this a common pattern? What's the downside, other than having to come up with another name?


1 Like

The only extra downside is the requirement that the new trait must also be implemented. Depending on the trait this can be a blanket impl and in that case it doesn't really matter much.

I know "type" will not work here.

Would be a valid argument to say that "type" was designed exactly for this type of use case? Just is currently not supported?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.