Into() cannot infer type even though the type annotation is given

In this code

pub struct Ytz<K, V> {
    table: std::collections::HashMap<K, V>,
}

impl<K, V> Ytz<K, V>
where
    K: std::cmp::Eq + std::hash::Hash + std::convert::Into<V>,
    V: std::ops::AddAssign + std::cmp::PartialOrd,
{
    pub fn new() -> Self {
        Self {
            table: std::collections::HashMap::<K, V>::new(),
        }
    }

    pub fn add(&mut self, item: &K) {
        if self.table.contains_key(item) {
            let to_add: V = *item.into(); // <--- here
            *self.table.get_mut(item).unwrap() += to_add;
        } else {
            self.table.insert(*item, *item.into());
        }
    }

    pub fn largest(&self) -> V {
        let mut result = self.table.values().nth(0).unwrap();
        for v in self.table.values() {
            if result < v.into() {
                result = v.into();
            }
        }
        *result
    }
}
error[E0282]: type annotations needed
  --> src/main.rs:18:35
   |
18 |             let to_add: V = *item.into();
   |                                   ^^^^ cannot infer type for `T`
   |
   = note: type must be known at this point

the type annotation is already given. Why can't the compiler infer the type?

*item.into() is *(item.into()) not (*item).into()

But just adding parenthesis won't work as you then get K is not copy errors. You could add Clone as a bound and do item.clone().into(), but since your always consuming item in add you should just take it by value (item: K instead of item: &K). You'll still need the Clone bound as you need two of item when inserting for the first time.

For your largest function, iterators have a max method so you can just write self.table.values().max().unwrap().clone()

4 Likes