Eyal leshem
Eyal leshem

Reputation: 1115

Rust compile error - cannot infer type for type parameter

I am trying to write a simple cache implementation in rust.

The general idea is to fetch serialized object from remote location, deserialize it, and save it the deserialized object in the local cache. I want to use the DeserializeOwned trait in the cache because the cached object lifetime is longer than the raw data.

I started with the following code:

use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::collections::HashMap; 

    
#[derive(Deserialize, Serialize)]
struct Demo{
    s: u32
}

pub struct Cache<T : DeserializeOwned> {
    cache: HashMap<String , T>, 
}

impl<T: DeserializeOwned> Cache<T> {
    pub fn new<K :DeserializeOwned>() -> Cache<K> {
        let cache  = HashMap::new(); 
        
        Cache {
            cache, 
        }

    }
}

fn main() {
    let cache = Cache::new::<Demo>(); 
}

and got the following error :

error[E0283]: type annotations needed
  --> src/main.rs:96:17
   |
84 |     pub fn new<K :DeserializeOwned>() -> Cache<K> {
   |                   ---------------- required by this bound in `Cache::<T>::new`
...
96 |     let cache = Cache::new::<Demo>(); 
   |                 ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
   |
   = note: cannot satisfy `_: DeserializeOwned`

But if i try to implement DeserializeOwned for Demo object the compiler complains about conflicting about conflicting implementation.

any help would be appreciated :)

Upvotes: 3

Views: 4002

Answers (1)

apetranzilla
apetranzilla

Reputation: 5919

You have two separate generic type parameters for Cache::new, and the fully qualified syntax with your example would be Cache::<Demo>::new::<Demo>(). This is probably not what you intended, since the type parameter on Cache itself is completely unused in Cache::new. Instead, I'd remove the type parameter from the function and instead use the existing type parameter from Cache, like so:

use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::collections::HashMap; 

    
#[derive(Deserialize, Serialize)]
struct Demo{
    s: u32
}

pub struct Cache<T : DeserializeOwned> {
    cache: HashMap<String , T>, 
}

impl<T: DeserializeOwned> Cache<T> {
    pub fn new() -> Cache<T> {
        let cache  = HashMap::new(); 
        
        Cache {
            cache, 
        }

    }
}

fn main() {
    let cache = Cache::<Demo>::new(); 
}

Playground link

Upvotes: 5

Related Questions