Helper method for a trait impl

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?

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).

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.

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.

1 Like

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.

1 Like

I don't have such a complicated method signature, but also faced that error. I liked the idea of using local functions:

impl fmt::Display for World {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    fn icon_for(world: &World, genome_id: GenomeId) -> char {
        '◼' // Will add logic here
    }

    for line in self.entities.as_slice().chunks(self.width as usize) {
        for &entity in line {
            let symbol = match entity {
                Entity::Nothing => ' ',
                Entity::Cell(genome_id) => icon_for(self, genome_id),
                Entity::Corpse(_) => '†',
            };
            write!(f, "{}", symbol)?;
        }
        write!(f, "\n")?;
    }

    Ok(())
}

}