Michael Galuza
Michael Galuza

Reputation: 407

Rust: conditional trait inheritance

For example, I want to write the trait for containers in Rust:

trait Container: Default {
    type ValueType;
}

But also I want that all Containers also can be Cloned only when Container::ValueType can be Cloned:

// not Rust code
trait Container: Default + Clone if Self::ValueType: Clone {
    type ValueType;
}

Of course, I could conditionally implement Clone trait for the concrete container itself:

struct MyVec<T> {}

impl<T: Clone> Clone for MyVec<T> {/**/}

or use derive(Clone), but I want to express my intention for Container trait, not for implementing types.

Upvotes: 4

Views: 1156

Answers (1)

kmdreko
kmdreko

Reputation: 60152

This similar syntax exists:

trait Container: Default + Clone where Self::ValueType: Clone {
                              // ^^^^^
    type ValueType;
}

But it isn't conditional, Container can only be implemented for types that statisfy all constraints: Default, Clone, and Self::ValueType is Clone.


I'm not sure this would be useful. Rust trait constraints are explicit, meaning you can't use something unless the constraint is there. So you'd have to include them in the constraints anyway.

fn use_container<C: Container>(c: C)
where
    C: Clone,
    C::ValueType: Clone
{
  let _ = c.clone();
  let _ = c.get_element().clone();
}

And you have to implement Clone on the concrete types regardless.

If your goal is just to indicate that "for implementations of Container if the elements are Clone then the container should be clone", the prevailing pattern in idiomatic Rust is to only constrain what you need when you need it. (i.e. if a function needs to clone the container, constrain on C: Clone; if a function only needs to clone an element, constrain on C::ValueType: Clone).

Upvotes: 8

Related Questions