Syntax question, "shortcut" to trait associated type when specifying generic type

Here's my broken code (will leave it to you to guess what I'm implementing!):

pub struct BlockChain<M, T>
where
    M: MerkleTree,
    H: <M::Hasher as MerkleHasher>::Element,
    T: TransactionList<Element=H>,
    for<'a> &'a M: IntoIterator, .....}

The line H: <M::Hasher as MerkleHasher>::Element, is failing at the < with "expected identifier, fournd <.

All I want is to be able to use H as an alias to <M::Hasher as MerkleHasher>::Element throughout the struct (as shown on the T: line). It's not intended to add any compile-time specifity to the struct.

This code compiles and seems to work, but I feel like I shouldn't need four generic types on the BlockChain struct when three of them are related to each other by associated traits:

pub struct BlockChain<H, HR, M, T>
where
    H: HashableElement,
    HR: MerkleHasher<Element = H>,
    M: MerkleTree<Hasher = HR>,
    T: TransactionList<Element = H>,
    for<'a> &'a M: IntoIterator, // TODO: MerkleTree should iterate over clones instead of references, I imagine very few uses of the iterator would not clone them anyway.

Here's another implementation that works, and only has the two generic types I actually need (M and T):

where
    M: MerkleTree,
    T: TransactionList<Element = <M::Hasher as MerkleHasher>::Element>,
    for<'a> &'a M: IntoIterator, // TODO: MerkleTree should iterate over clones instead of references, I imagine very few uses of the iterator would not clone them anyway.

However, this leads to unwieldy syntax including the T line above, and this behemoth inside the struct:

   snapshot_root_hash: <<M::Hasher as MerkleHasher>::Element as HashableElement>::Hash,

If it's not clear, the "tree of traits" in this case is:

MerkleHash: Clone + PartialEq;
HashableElement has type Hash: MerkleHash;
MerkleHasher: has type Element: HashableElement;
MerkleTree: has type Hasher: MerkleHasher;

Hoping this is a simple question of syntax!

You can use type aliases to simplify projections:

type ElemOf<M> = <<M as MerkleTree>::Hasher as MerkleHasher>::Element;

type HashOf<M> = <ElemOf<M> as HashableElement>::Hash;

struct BlockChain<M, T>
where
    M: MerkleTree,
    T: TransactionList<Element = ElemOf<M>>,
    for<'a> &'a M: IntoIterator,
{
    snapshot_root_hash: HashOf<M>,
...
}
1 Like

Thanks, I didn't realize you can put a generic on a type alias.