The Mungler
The Mungler

Reputation: 166

Compiler says to add type parameters, but I don't think I can in this context

The compiler complains that type annotations are needed. I was able to fix it by creating an unused variable with type parameters, commented out in the code snippet below. This feels like a weird workaround though, is there some way to add type parameters without needing to do this? It just seems like rust should know the type of key because Map is a defined type.

type Map = Arc<DashMap<[u8; 32], Session>>;

pub struct SessionManager {
    map: Map,
    db_wtx: WriteTx,
    db_rtx: ReadTx,
}

impl SessionManager{
    pub fn logout(&self, token: &str) {
        if let Ok(decoded_vec) = base64::decode(token) {
            if let Ok(key) = decoded_vec.try_into() {
                //let _typed_key: [u8; 32] = key;
                self.map.remove(&key);
            }
        }
    }
}

Error msg:

error[E0282]: type annotations needed
   --> src/login_handler.rs:244:14
    |
244 |             if let Ok(key) = decoded_vec.try_into() {
    |                       ^^^    ---------------------- this method call resolves to `Result<T, <Self as TryInto<T>>::Error>`
    |                       |
    |                       cannot infer type

edit: for clarity I'm using the dashmap crate, which tries to mimic the api of std::hashmap closely while allowing multithreaded access.

Upvotes: 1

Views: 170

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 71485

rustc can't infer the type because Map::remove() (assuming you're actually talking about HashMap, or BTreeMap) doesn't take &K as the parameter type (where K is the key type), but rather some Q where Q: Borrow<K>. This allows for more flexibility (for example, passing a &str for a map of Strings), but come at the cost of worse inference.

There are few alternatives: You can specify the type for the Ok:

if let Ok::<[u8; 32], _>(key) = decoded_vec.try_into()

This is a shorthand for:

if let Result::<[u8; 32], _>::Ok(key) = decoded_vec.try_into()

Or you can use TryFrom instead of TryInto:

if let Ok(key) = <[u8; 32]>::try_from(decoded_vec)

If you choose a variable, note that it is preferred to use _ and not another underscore-prefixed name like _typed_key. This is because _ does not move the value, but any other name does. This is not relevant in this case since [u8; 32] is Copy, but still a good practice.

Upvotes: 1

Related Questions