Helper method for a trait impl


#1

I’m implementing a method of a trait. To avoid the method becoming huge spaghetti code I want to break down the implementation into smaller methods.

Unfortunately when I add other “private” methods to the trait impl, I’m getting error E0407.

trait QuackTwice {
    fn quack_twice();
}

impl<T> QuackTwice for Complicated<Type> where Lots<Of::Things<Tediously<T>>>: Declared {
    fn quack_twice() {
        Self::quack();
        Self::quack();
    }

    fn quack() {
       // implementation
    }
}

This limitation is annoying because if I move quack anywhere else, I’ll have to repeat the Lots<Of::Things<Tediously>>: Declared part, which in my particular case is 5 lines of complex declarations.

Can I add “private” helper methods to trait implementations? If not, is there another way to move code into a helper method without duplicating the painfully large where clause?


#2

You can:

  1. Create a Lots<Of::Things<Tediously>> type alias (FYI, type aliases can be generic).
  2. Add your private helper methods to the Complicated<Type> implementation directly.
  3. Create a private helper trait.
  4. Create a macro for the where clause (maybe?)…

Unfortunately, you can’t:

  1. Have private trait methods.
  2. “Save” where constraints (without macros).

#3

Thanks. I’ve tried alias, but it’s quite limited:

type FromTuple<T> = From<(T,T)>;

pub trait Foo {}

impl<T> Foo for [T] where T: Copy + FromTuple<T> {}

error[E0404]: FromTuple is not a trait

and I think it can’t handle T: Foo + Bar + Baz.

I can’t add my helper method to the complicated type, as the method depends on bounds specified in where. AFAIK the best I can do is a generic method on the type, with all of where copy&pasted.


#4

Aliases really only work for simplifying types (e.g. MyAlias: Copy + Debug).

Can’t you just use the same where clause?

impl<T> Complicated<Type> where Lots<Of::Things<Tediously<T>>>: Declared {
    fn quack() {
       // implementation
    }
    // Other functions...
}

Of course, this doesn’t help if every helper method needs a different where clause.


#5

Well, use type for types and trait for traits. If you want to have a trait that captures a bunch of traits, do this:

pub trait FromTuple<T>: From<(T,T)> {}
impl<T, AllMyTypes> FromTuple<T> for AllMyTypes: From<(T,T)> {}

pub trait Foo {}

impl<T> Foo for [T] where T: Copy + FromTuple<T> {}

If you want to frequently add the constraint T: Foo + Bar + Baz, make a similar alias for it:

pub trait Value: Foo + Bar + Baz {}
impl<T: Foo + Bar + Baz> Value for T {}

and use T: Value everywhere you need it. You can even constraint the impl for FromTuple by T: Value.