Need help extending a trait


#1

Hi everyone,

I’m trying to do something with Rust that I think should be possible, but which I am unclear on how to do.

I have a struct

struct X<'a> {
...
}

There are several structs that will implement the From trait using this trait like so:

struct A {
...
}

impl <'a> From <&'a X<'a>> for A {
...
}

Now, I want my own trait, Y, that guarantees that structs implementing it will also implement trait X. The problem is I don’t know what to do with the lifetime parameter. How do I declare Y so that it doesn’t itself have a lifetime parameter and so that it ensures implementation of From as demonstrated above?

Thanks in advance!


#2

Unfortunately this is impossible, if a Trait has forced implementation of another trait, then it’s logical that the first trait uses everything that the trait it’s forcing the implementation of provides. Here is a playground which demonstrates this. Now, then again, trait Y in the example doesn’t have to use 'a, it only has to pass it on to XFrom to then be used there. In a sense Y can be oblivious about the lifetime


#3

Thanks! Very helpful. Your explanation makes sense.


#4

Actually it is possible, but there is a catch

This is an editted version of @OptimisticPeach’s example
playground link

//dummy from trait
trait X<'a> { }

trait Y: for<'z> X<'z> { }

struct Foo;
struct Bar<'a, 'b: 'a>(&'a &'b ());

impl<'a> X<'a> for Foo {}

impl<'a> Y for Foo {}

impl<'a, 'b: 'a> X<'b> for Bar<'a, 'b> {}

// This won't work because X is not implemented for Bar for *all* lifetimes,
// only those that outlive `'a`
impl<'a, 'b: 'a> Y for Bar<'a, 'b> {}

The change is in the bounds for trait Y, you can see for<'a> X<'a>, this reads as for all lifetimes ('a), Self must implement X<'a>. The catch is that it must be implemented for all lifetimes. As you can see in the example, it is fine to implement Y for Foo because Foo implements X<'a> for all lifetimes 'a, but it is not fine to implemnt Y for Bar because Bar<'a, 'b> only implements X<'b> for all lifetimes 'b that outlive lifetime 'a.

If you have more complex lifetimes requirements, then you will need to propagate lifetimes through your traits.


#5

Oh, that’s interesting! I wasn’t aware that there were lifetime parameters available in for, where is it mentioned in the docs?


#6

The Rust nomicon has it, you can also search for it under Higher Rank Type Bounds (HRTB)

https://doc.rust-lang.org/nomicon/hrtb.html


please note that this has nothing to do with for loops. Even though they share some syntax