I tried to write two traits where one requires another to be implemented and got this error:
error[E0277]: the trait bound `T: ValTrait` is not satisfied
--> src/main.rs:20:1
|
20 | / fn get<T: ValRequireTrait + std::fmt::Debug>(_t: T) {
21 | | println!("{:?}", T::VAL);
22 | | }
| |_^ the trait `ValTrait` is not implemented for `T`
|
= help: consider adding a `where T: ValTrait` bound
= note: required by `ValRequireTrait`
The code:
trait ValTrait<T = Self> {
const VAL: T;
}
trait ValRequireTrait<T: ValTrait = Self> {}
#[derive(Debug, Copy, Clone)]
struct A {
field: u64,
}
impl ValTrait for A {
const VAL: A = A {
field: 0u64
};
}
impl ValRequireTrait for A {}
fn get<T: ValRequireTrait + std::fmt::Debug>(_t: T) {
println!("{:?}", T::VAL);
}
fn main() {
let a = A { field: 6u64 };
get(a);
}
How to do this correctly? If I do what the compiler says I will not need the ValRequireTrait
because it will be useless. I wanted ValRequireTrait
to be a mark that the structure implements enough methods as I need.
In other words, I expect such a requirement be transitive so when in get()
function I require one trait (ValRequireTrait
), others (ValTrait
) will be required automatically without any specification in the code as compiler wants.
A trait is similar to a class but for grouping methods in a fine-grained and consistent way. It is not allowed to instantiate a trait on its own. So a trait is just a container for a group of methods that you can reuse in another classes.
To implement a trait, declare an impl block for the type you want to implement the trait for. The syntax is impl <trait> for <type> . You'll need to implement all the methods that don't have default implementations.
Traits can't have fields. If you want to provide access to a field from a trait, you need to define a method in that trait (like, say, get_blah ).
Rust is not an object oriented language. And traits are not exactly interfaces.
It sounds like you want ValTrait
to be a supertrait of ValRequireTrait
. A good introduction can be found in the Rust book (2nd edition):
Sometimes, we may want a trait to be able to rely on another trait also being implemented wherever our trait is implemented, so that our trait can use the other trait’s functionality. The required trait is a supertrait of the trait we’re implementing.
If you change this line:
trait ValRequireTrait<T: ValTrait = Self> {}
to this, it compiles fine:
trait ValRequireTrait<T: ValTrait = Self>: ValTrait<T> {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With