Type annotation needed

Hi, I don't understand why I'm getting this error. If somebody could explain and provide a solution I'd be grateful.
Function calculate_hash, taken from:

During compilation, I'm getting: type annotation needed. I thought that that's the whole point of generics so I don't have to specify concrete type?
Thanks in advance.

P.S.
Don't mind the code as a whole, it is a W.I.P. I've pasted it here so you have something that's should compile except that calculate_hash.

use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::default::Default;
use std::vec::Vec;

pub struct HashMap<K, V>
where
    K: Default + Hash,
{
    array: Vec<(K, V)>,
    key: K,
}
impl<K, V> Default for HashMap<K, V>
where
    K: Default + Hash,
{
    fn default() -> Self {
        HashMap {
            array: Vec::new(),
            key: K::default(),
        }
    }
}
impl<K, V> HashMap<K, V>
where
    K: Default + Hash,
{
    pub fn new(initial_size: usize) -> Self {
        HashMap {
            array: Vec::with_capacity(initial_size),
            key: K::default(),
        }
    }
    pub fn add(&mut self, pair: (K, V)) {
    HashMap::calculate_hash(&pair.0);///HERE<< what type annotations?
    }
    pub fn remove(&mut self, key: K) {}
    pub fn get(&self, key: K) -> V {
        unreachable!()
    }

    fn calculate_hash<T: Hash>(t: &T) -> u64 {
        let mut s = DefaultHasher::new();
        t.hash(&mut s);
        s.finish()
    }
}

OK, got it. It was complaining about the HashMap, so it should be HashMap<K,V> not about calculate_hash.

The expanded error message is this:


   Compiling playground v0.0.1 (/playground)
error[E0283]: type annotations needed
  --> src/lib.rs:35:5
   |
35 |     HashMap::calculate_hash(&pair.0);
   |     ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `K`
...
42 |     fn calculate_hash<T: Hash>(t: &T) -> u64 {
   |     ---------------------------------------- required by `HashMap::<K, V>::calculate_hash`
   |
   = note: cannot satisfy `_: std::default::Default`

This tells you that it can’t figure out what type K should be when calling HashMap::<K, V>::calculate_hash. For all it knows, you might want to call the version defined on HashMap<String,String> instead of HashMap<K,V>— They are identical right now, but that isn’t always true.

The general solution is the one you’ve already found, to explicitly state HashMap’s type parameters. There is a shorthand you can use for this case, though: Because this code is inside an impl HashMap<K,V> block, you can call Self::calculate_hash instead:

pub fn add(&mut self, pair: (K, V)) {
    Self::calculate_hash(&pair.0);
}

(Playground)

1 Like