Search code examples
rustassociated-types

Compiler doesn't see associates type is the same as concrete type


I have a little nuisance in my project, that I can't resolve: The compiler doesn't see that the associated type is the same as the concrete type and won't let my do an assignement.

Playground

Does anyone know how to fix it. Thank you for taking your time.

Artos

// This program fails to compile 
// Compiler doesn't see that the associated type and type of user id are the same. 
struct User {
    pub id: u64,
}

trait KeyTrait {
    type Key;
    fn key(&self) -> Self::Key;
}

impl KeyTrait for User {
    type Key = u64;
    fn key(&self) -> Self::Key {
        self.id
    }
}

trait PrintTrait {
    fn print_key<K: KeyTrait>(key: K);
}

impl PrintTrait for User {
    fn print_key<K: KeyTrait>(key_impl: K) {
        let id: u64 = key_impl.key(); // Raises error: expected u64, found associated type

        println!("Found key {}", id);
    }
}

fn main() {
    let user = User { id: 5 };
    User::print_key(user);
}

Solution

  • This code makes the assumption that every implementation of KeyTrait has the same associated Key type.

    impl PrintTrait for User {
        fn print_key<K: KeyTrait>(key_impl: K) {
            let id: u64 = key_impl.key();
            println!("Found key {}", id);
        }
    }
    

    In fact, an implementation of KeyTrait could choose any type.

    You can encode this assumption in the type system:

    trait PrintTrait {
        fn print_key<K>(key: K)
        where
            K: KeyTrait<Key = u64>;
    }
    
    impl PrintTrait for User {
        fn print_key<K>(key_impl: K) 
        where
            K: KeyTrait<Key = u64>,
        {
            let id: u64 = key_impl.key();
        }
    }
    

    Or, if you need PrintTrait to be generic over all possible associated Key types:

    trait PrintTrait<T> {
        fn print_key<K>(key: K)
        where
            K: KeyTrait<Key = T>;
    }
    
    impl PrintTrait<u64> for User {
        fn print_key<K>(key_impl: K) 
        where
            K: KeyTrait<Key = u64>,
        {
            let id: u64 = key_impl.key();
        }
    }