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.
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()
}
}