Reduce repetitive generic parameters and struct name in impl syntax

With implied trait bound (accepted but not implemented), you could do the same but with less line numbers:

struct Vec2<X, Y>(pub X, pub Y)
where
    X: Add<Output=X> + Mul<Output=X> + Neg<Output=X>,
    Y: Add<Output=Y> + Mul<Output=Y> + Neg<Output=Y>;
impl<X, Y> Add for Vec2<X, Y> { ... }
impl<X, Y> Mul for Vec2<X, Y> { ... }
impl<X, Y> Neg for Vec2<X, Y> { ... }

Although I need to repeat impl<X, Y> but I don't care much.

3 Likes

I think that implied trait bound is the first step, mostly because it solves much more issue, but both proposal coexist really well.

trait Trait { ... }
fn foo<T: Trait>(t: T);

struct Vec2<X, Y>(pub X, pub Y)
where
  X: Trait,
  Y: Trait;

fn bar<X, Y>(vec: Vec2<X, Y>)
where
  X: Trait,
  Y: Trait;
{
    // foo() parameters must implement trait, so the
    // bounds are required in the definition of Vec2
    foo(vec.0);
    foo(vec.1);
}

With implicit trait bounds:

trait Trait { ... }
fn foo<T: Trait>(t: T);

struct Vec2<X, Y>(pub X, pub Y)
where
  X: Trait,
  Y: Trait;

fn bar<X, Y>(vec: Vec2<X, Y>)
// no explicit bounds, but the compilers knows that X and Y impl Trait
{
    foo(vec.0);
    foo(vec.1);
}

With both proposals:

trait Trait { ... }

for <T>
where T: Trait {
    fn foo(t: T);

    struct Vec2(pub X, pub Y);

    fn bar(vec: Vec2<X, Y>) {
        foo(vec.0);
        foo(vec.1);
    }
}
1 Like

Stabalising trait aliases would solve a lot of the issues here.

I'm not sure what their current status is but my compiler tells me they are experimental.

Another note on impls is often you want different generic constrhints for different impls.

impl <T> Thing<T>{
    pub fn run(&self){/*...*/}
}

impl <T:Clone> Thing<T>{
    pub fn do_copy_thing(&self){/*...*/}
}

Having the separate impls each wtih their own constraints makes the type system really nice to work with

1 Like

I don't think it's always the case necessary to have all the generics copied to impl, usually people strives to reduce the generics used in the impl blocks to reduce compilation time. Even in the example @KSXGitHub gave, GetStyle does not seemed to be able to use that, I think this would split the syntax to be usable only in some special case (or common case). It felt like the introduction of a single constructor (new method) in many languages which then they needed additional complexity to remove that (like classmethod in python), although common but is indeed a special case.