1

I'm not sure how exactly to formulate this question so I will illustrate by example.

I am using the bitflags crate which provides a trait called Flags. The flags trait involves the presence of an associated type, something like

pub trait Flags: Sized + 'static {
    /// The underlying bits type.
    type Bits: Bits;

    fn from_bits(bits: Self::Bits) -> Option<Self> {
        ... 
    }

    ...
}

where the Bits trait is implemented for the following

i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize

I then wish to define a trait (Register) which inherits Flags but adds the requirement that an associated constant be defined upon implementation. Something like

trait Register: Flags {
    const ADDRESS: u8;

    fn address(&self) -> u8 {
        Self::ADDRESS
    }
}

Having access to a Flags with an attached address would allow me to do useful things, but some of these useful things rely on the Flags implementation to have the Bits type be u8. I end up in a situation where I have

trait Register: Flags {
    const ADDRESS: u8;

    fn address(&self) -> u8 {
        Self::ADDRESS
    }

    fn do_something(&self) {
        let new_bits_data: u8 = ...;
        *self = Self::from_bits(new_bits_data).unwrap()
    }
}

And calling Self::from_bits() doesn't work because we don't yet know the type of the Bits which a specific implementation of Flags will have.

In my mind I would like to be able to define the Register trait only for the subset of Flags implementations which have set

type Bits = u8;

but I don't know if that is a good idea or even possible.

Do you have any ideas for how I might work around this issue or if it is possible to implement what I want?

I have considered the idea of defining a trait Flags_u8 which is the same as Flags with the constraint that the Bits type is u8. But I don't know how that would look.

1 Answer 1

3

You can constrain associated types of super traits similar to what you can do for any trait:

trait Register: Flags<Bits = u8> { ... }

Or for a specific method:

trait Register: Flags {
    const ADDRESS: u8;

    fn address(&self) -> u8 {
        Self::ADDRESS
    }

    fn do_something(&self)
    where
        Self: Flags<Bits = u8>,
    {
        let new_bits_data: u8 = ...;
        *self = Self::from_bits(new_bits_data).unwrap()
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

I totally forgot to thank you for this. It's exactly what I needed!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.