Associated types mismatch

i thought <<BlockTr as BlockT>::Hdr as HeaderT>::H is the same as <H as Hbl>::Output here:

#![feature(associated_type_defaults)]
use std::collections::HashMap;
use std::hash::Hash;

trait Hbl {
    type Output = Keccak;
    fn hash(bytes: &[u8]) -> Self::Output;
}

struct Keccak;
impl Hbl for Keccak {
    type Output = [u8; 32];
    fn hash(bytes: &[u8]) -> Self::Output {
        todo!()
    }
}
trait HeaderT {
    type H = <Keccak as Hbl>::Output;
    fn new(h: Self::H) -> Self;
}

struct Header<H: Hbl> {
    hash: <H as Hbl>::Output,
}

impl<H: Hbl> HeaderT for Header<H> {
    type H = <H as Hbl>::Output;
    fn new(hash: H::Output) -> Self {
        Header { hash }
    }
}

trait BlockT {
    type Hdr: HeaderT;
    fn new(header: Self::Hdr) -> Self;
}

struct BlockImpl<H: HeaderT> {
    header: H,
}

impl<H: HeaderT> BlockT for BlockImpl<H> {
    type Hdr = H;
    fn new(header: Self::Hdr) -> Self {
        BlockImpl { header }
    }
}

struct Chain<H: Hbl, BlockT> {
    map: HashMap<H::Output, BlockT>,
}

impl<H: Hbl, BlockT> Chain<H, BlockT> {
    fn new() -> Self {
        Chain {
            map: HashMap::new(),
        }
    }
    fn insert(&self, k: H::Output, v: BlockT) {}
}

struct Api<H: Hbl, Block: BlockT> {
    chain: Chain<H, Block>,
}

impl<H: Hbl, BlockTr: BlockT> Api<H, BlockTr> {
    fn new(chain: Chain<H, BlockTr>) -> Self {
        Api { chain }
    }

    fn create(&self) {
        let d = <H as Hbl>::hash(b"abhi");
        let h = <<BlockTr as BlockT>::Hdr as HeaderT>::new(d);
        // let b = BlockTr::new(h);
        // self.chain.insert(d, b);
    }
}

fn start<H: Hbl, BlockTr: BlockT>(chain: Chain<H, BlockTr>) {
    let api = Api::new(chain);
}

fn main() {
    let chain = Chain::<Keccak, BlockImpl<Header<Keccak>>>::new();
    start(chain);
}

the error:

error[E0308]: mismatched types
  --> src/main.rs:73:60
   |
73 |         let h = <<BlockTr as BlockT>::Hdr as HeaderT>::new(d);
   |                 ------------------------------------------ ^ expected `HeaderT::H`, found `Hbl::Output`
   |                 |
   |                 arguments to this function are incorrect
   |
   = note: expected associated type `<<BlockTr as BlockT>::Hdr as HeaderT>::H`
              found associated type `<H as Hbl>::Output`
   = note: an associated type was expected, but a different one was found
note: associated function defined here
  --> src/main.rs:19:8
   |
19 |     fn new(h: Self::H) -> Self;
   |        ^^^

here's the permalink to playground: Rust Playground

Why would they be the same? They are two different associated types of two completely unrelated type variables. They can be literally anything at this point.

Just because there happens to be some pairs of concrete types implemented in a way that these associated types coincide, it isn't necessarily the case that they must always be the same in general (ie., for every possible choice of substitutions for both type variables).

If you want to restrict the method to pairs of types related like that, you have to include that in the trait bounds, just like any other generic constraint you want to rely on.

1 Like

wow! i had no idea you could set an associated type using syntax to set a default type on a generic type param. believe me, i was thinking about ways to do just this but just couldn't figure out this syntax. thank you!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.