Unused traits


“Recently” Bjarne Stroustrup has said that when you use C++ concepts you should’t strive to use the minimal concepts that allow a templated function to compile, and instead you should use a coherent and organic concept that could include more than what you scrictly need. Otherwise you risk restricting too much the future implementations of your function, because a different algorithm could need a slightly different group of Concepts.

While Rust doesn’t have C++ concepts, I think those words of Stroustrup could be good for Rust too. Yet, sometimes I prefer to not over-constrain a generic function in Rust, so I’d like it to not use useless traits, like here where Debug is not used by the function:

fn quicksort<T: Copy + Ord + Debug>(a: &mut [T]) {
    if a.len() < 2 { return; }
    let pivot = a[a.len() / 2];

    let (mut i, mut j) = (0, a.len() - 1);
    loop {
        while a[i] < pivot { i += 1; }
        while a[j] > pivot { j -= 1; }
        if i >= j { break; }
        a.swap(i, j);
        i += 1;
        j -= 1;

    quicksort(&mut a[.. i]);
    quicksort(&mut a[i ..]);

“Recently” some HashMap functions have being modified to remove unnecessary Debug constraints ( https://github.com/rust-lang/rust/issues/41924 ), like here:

impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> {

So is it possible and a good idea to add a warning (or a lint for Clippy) that spots unnecessary trait constraints in generic functions?


http://www.stroustrup.com/good_concepts.pdf is a good read on this (might be what you’re referring to @leonardo).


That’s the paper I have read, thank you. Bjarne says:

Thus, the ideal is not “minimal requirements” but “requirements expressed in terms of fundamental and complete concepts.” This puts a burden on the designers of types (to match concepts), but that leads to better types and to more flexible code


Interestingly, it seems part of his argument stems from C++'s duck typing:

To be more realistic, people sometimes get into trouble defining something like this:

template<typename T>
concept bool Addable = requires(T a, T b) { { a+b } -> T; } ;

They are then often surprised to find that std::string is Addable (std::string provides a +, but that + concatenates, rather than adding). Addable is not a suitable concept for general use, it does not represent a fundamental user-level concept. If Addable, why not Subtractable? (std::string is not Subtractable, but int* is). Surprises are common for “simple, single property concepts.” Instead, define something like Number: […]

And I’d continue that thought, but I’m also getting some mighty wicked deja vu right now. Have I… like, have I quoted this exact block of text before or something?

…nah. Must be my imagination.