Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to require a trait in another trait correctly?

Tags:

rust

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.

like image 949
Victor Polevoy Avatar asked Dec 21 '17 10:12

Victor Polevoy


People also ask

Can trait use another trait?

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.

How do you implement a trait?

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.

Can traits have fields Rust?

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

Are Rust traits interfaces?

Rust is not an object oriented language. And traits are not exactly interfaces.


1 Answers

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> {}
like image 163
StarSheriff Avatar answered Sep 28 '22 03:09

StarSheriff