Define trait using HRTBs

trait GenericNum
where
    Self: Sized + Add<Self, Output = Self>,
    for<'a> Self: Add<&'a Self, Output = Self>,
    for<'a> &'a Self: Add<Output = Self> + Add<&'a Self, Output = Self>,
{
}

When I define a trait like this, it's all fine. But when I define a function using this trait.

fn my_add<T: GenericNum>(a: T, b: T) -> T {
    a + &b + &b
}

Error happens:

20 | trait GenericNum
   |       ---------- required by a bound in this trait
...
24 |     for<'a> &'a Self: Add<Output = Self> + Add<&'a Self, Output = Self>,
   |                       ^^^^^^^^^^^^^^^^^^ required by this bound in `GenericNum`
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
   |
28 | fn my_add<T: GenericNum>(a: T, b: T) -> T where for<'a> &'a T: Add {
   |                                           ++++++++++++++++++++++++

For more information about this error, try `rustc --explain E0277`.

It seems that the trait bound for &' a Self dosen't work.So why can't I define trait like this?

You have to repeat non-supertrait bounds everywhere, so:

fn my_add<T: GenericNum>(a: T, b: T) -> T
where
    for<'a> &'a T: Add<Output = T> + Add<&'a T, Output = T>,
{
    a + &b + &b
}

See: https://github.com/rust-lang/rust/issues/20671

And also: 2089-implied-bounds - The Rust RFC Book

The RFC is accepted but not stable. I'm not sure what the outlook is, as it has negative consequences too.

3 Likes

Thank you for your explanation!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.