Code Smell

While experimenting in Rust, I found myself often using the same trait bounds over and over.

1
2
3
4
5
6
7
8
use std::{cmp, hash, fmt}

pub struct Chunk<T: cmp::Eq + hash::Hash + fmt::Display + Copy + ChunkKey> { ... }

async fn receive_chunks<
  T: cmp::Eq + hash::Hash + fmt::Display + Copy + ChunkKey 
  U: cmp::Eq + hash::Hash + fmt::Display + Copy + ChunkKey 
>(...) { ... }

Repeating these trait bounds over and over would lead to increased maintenance cost if I ever needed to add or remove a trait bound and I was repeating myself unnecessarily.

The Solution

To solve this, you could declare a trait which implemented all these trait bounds so that you can replace all future uses of the trait bounds with this new “alias”.

1
2
3
4
5
6
7
8
use std::{cmp, hash, fmt}

pub trait DropKey: cmp::Eq + ChunkKey + hash::Hash + Copy + fmt::Display {}
impl<T> DropKey for T where T: cmp::Eq + ChunkKey + hash::Hash + Copy + fmt::Display {}

pub Struct Chunk<DropKey>

async fn receive_chunks<T: DropKey, U: DropKey>(...) { ... }