I'm trying to create a supertrait with a few convenient bounds, including requirements on &Self
. So for example, say I want an AddAny
trait which allows all of these: x + y
, x + &y
, &x + y
, &x + &y
.
Implementing the first two variations is easy, and works fine: Rust Playground
use std::ops::Add;
trait AddAny
where Self: Sized + Add<Self, Output=Self>,
for<'b> Self: Add<&'b Self, Output=Self>,
{}
impl<T> AddAny for T
where T: Add<T, Output=T>,
for<'b> T: Add<&'b T, Output=T>,
{}
fn add_val_val<T: AddAny>(x: T, y: T) -> T { x + y }
fn add_val_ref<T: AddAny>(x: T, y: &T) -> T { x + y }
fn main() {
println!("{}", add_val_val(2, 3));
println!("{}", add_val_ref(2, &3));
}
That's pared down from my attempt at a full solution, which doesn't work: Rust Playground
use std::ops::Add;
trait AddAny
where Self: Sized + Add<Self, Output=Self>,
for<'b> Self: Add<&'b Self, Output=Self>,
for<'a> &'a Self: Add<Self, Output=Self>,
for<'a, 'b> &'a Self: Add<&'b Self, Output=Self>
{}
impl<T> AddAny for T
where T: Add<T, Output=T>,
for<'b> T: Add<&'b T, Output=T>,
for<'a> &'a T: Add<T, Output=T>,
for<'a, 'b> &'a T: Add<&'b T, Output=T>
{}
fn add_val_val<T: AddAny>(x: T, y: T) -> T { x + y }
fn add_val_ref<T: AddAny>(x: T, y: &T) -> T { x + y }
fn add_ref_val<T: AddAny>(x: &T, y: T) -> T { x + y }
fn add_ref_ref<T: AddAny>(x: &T, y: &T) -> T { x + y }
fn main() {
println!("{}", add_val_val(2, 3));
println!("{}", add_val_ref(2, &3));
println!("{}", add_ref_val(&2, 3));
println!("{}", add_ref_ref(&2, &3));
}
errors:
<anon>:17:1: 17:53 error: the trait `for<'a> core::ops::Add<T>` is not implemented for the type `&'a T` [E0277]
<anon>:17 fn add_val_val<T: AddAny>(x: T, y: T) -> T { x + y }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:17:1: 17:53 help: see the detailed explanation for E0277
<anon>:17:1: 17:53 note: required by `AddAny`
<anon>:17:1: 17:53 error: the trait `for<'b, 'a> core::ops::Add<&'b T>` is not implemented for the type `&'a T` [E0277]
<anon>:17 fn add_val_val<T: AddAny>(x: T, y: T) -> T { x + y }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:17:1: 17:53 help: see the detailed explanation for E0277
<anon>:17:1: 17:53 note: required by `AddAny`
(repeated for each of those generic functions)
So T
, which I'm constraining to types that have implemented AddAny
, is somehow failing to actually have AddAny
implemented? Huh?
I thought maybe I was writing the impl wrong, but even removing all that errors the same way. Rust Playground
use std::ops::Add;
trait AddAny
where Self: Sized + Add<Self, Output=Self>,
for<'b> Self: Add<&'b Self, Output=Self>,
for<'a> &'a Self: Add<Self, Output=Self>,
for<'a, 'b> &'a Self: Add<&'b Self, Output=Self>
{}
fn add_val_val<T: AddAny>(x: T, y: T) -> T { x + y }
fn add_val_ref<T: AddAny>(x: T, y: &T) -> T { x + y }
fn add_ref_val<T: AddAny>(x: &T, y: T) -> T { x + y }
fn add_ref_ref<T: AddAny>(x: &T, y: &T) -> T { x + y }
fn main() { }
So it seems like the &Self
bounds make this impossible to be satisfied. Is there any way to express this?