Home > Enterprise >  Rust: Convenience syntax for specifying types on trait implementations?
Rust: Convenience syntax for specifying types on trait implementations?

Time:06-26

Consider the following code with a struct S with a constrained generic type parameter Idx and a default value for Idx.

use num::{PrimInt, Unsigned};

struct S<Idx = u32>
where
    Idx: Unsigned   PrimInt, {
    // ... Some fields
}

impl<Idx: Unsigned   PrimInt> Clone for S<Idx> {
    fn clone(&self) -> Self {
        S {}
    }
}

impl<Idx: Unsigned   PrimInt> Eq for S<Idx> {
    fn eq(&self, rhs: &Self) -> bool {
        true
    }
}

I would like to implement a bunch of traits for S, but I find always specifying the constraints for the Idx type parameter tedious. If I don't specify Idx on a trait implementation, the code compiles but only has an implementation for Idx = u32.

Is there some convenience syntax where I don't have to specify the Idx: Unsigned PrimInt all the time but still correctly implements the traits?

CodePudding user response:

There isn't a syntax built in, but you can make one yourself using macros:

macro_rules! s_impl {
    ( $($t:path => $i:tt)  ) => {
        $(impl<Idx: Unsigned   PrimInt> $t for S<Idx> $i) 
    }
}

Then you can do:

s_impl!(
    Clone => {
        fn clone(&self) -> Self {
            S {}
        }
    }
    PartialEq => {
        fn eq(&self, rhs: &Self) -> bool {
            true
        }
    }
);

CodePudding user response:

The answer from @cdhowie is correct, but I would like to point that there is an accepted (but not yet implemented, as of time of writing) RFC to allow you to omit such bounds - RFC #2089 Implied Bounds.

It is not yet clear what will be the form of the feature, though, because it is a semver hazard.

  • Related