Trait bounded by traits and lifetime parameters


#1

I have two structs, A and B, that implement a common trait X. A and B should also implement some traits from the standard library, in particular Eq, Copy, Hash and From. So, I ended up with this code:

use std::hash::Hash;

#[derive(Eq, PartialEq, Copy, Clone, Hash)]
struct A;

#[derive(Eq, PartialEq, Copy, Clone, Hash)]
struct B;

trait X : Eq + Copy + Hash {
    fn useful(self);
}

impl X for A {
    fn useful(self) {}
}

impl X for B {
    fn useful(self) {}
}

This is nice, because I can now use trait X in generic functions to abstract over A or B:

fn do_useful_thing<T: X>(arg: T) {
    arg.useful();
}

Now, I don’t know how to deal with From because I need to use a lifetime parameter for him. What I want to do is this:

trait X : Eq + Copy + Hash + From<&[u8]>

This doesn’t work (error: missing lifetime specifier)

trait X : Eq + Copy + Hash + From<&'a [u8]>

This doesn’t work either (use of undeclared lifetime name 'a)

trait X<'a> : Eq + Copy + Hash + From<&'a [u8]>

This works, but now I have to add a lifetime parameter everywhere I use X.

impl<'a> X<'a> for A { ...
fn do_useful_thing<'a, T: X<'a>>(arg: T) { ...

How can I define my trait X, so that it can be used easily and encompasses all the capabilities of my structs?

Thanks!


What are the for in types in Rust?
#2

The trick is for<'a> (for all 'a).

use std::hash::Hash;

#[derive(Eq, PartialEq, Copy, Clone, Hash)]
struct A;

#[derive(Eq, PartialEq, Copy, Clone, Hash)]
struct B;

trait X : Eq + Copy + Hash + for<'a> From<&'a [u8]> {
    fn useful(self);
}

impl X for A {
    fn useful(self) {}
}

impl<'a> From<&'a [u8]> for A {
    fn from(_: &'a [u8]) -> A {
        A
    }
}

impl X for B {
    fn useful(self) {}
}

impl<'a> From<&'a [u8]> for B {
    fn from(_: &'a [u8]) -> B {
        B
    }
}

#3

Thanks! And it even works on stable Rust, yay!

Does this syntax have an alternative name? I can’t find any reference of it using Google.

Edit: Actually, I found the relevant RFC by myself.
Edit2: Also, I found a reference in the Rustonomicon.


#4

The link to Rustonomicon is broken. Working link: https://doc.rust-lang.org/nomicon/hrtb.html.