I want to create a trait for Map with the following definition:

```
pub trait Map<K: Sync, V> {
    fn put(&mut self, k: K, v: V) -> Option<V>;
    fn upsert<U: Fn(&mut V)>(&self, key: K, value: V, updater: &U);
    fn get<Q: ?Sized>(&self, k: &Q) -> Option<V> where K: Borrow<Q>, Q: Eq + Hash + Sync;
    // other methods ommited for brevity
}

```

Now, the problem is that if I implement this trait, for example as **MyHashMap**, then I cannot have an expression like this:

```
let map: Box<Map<i32, i32>> = Box::new(MyHashMap::<i32, i32>::new());

```

The error would be:

> 
> the trait `map::Map` cannot be made into an object
> 
> 
> 

How can one solve this issue? Because it's not a good idea to start using a Map implementation directly, as it's not a good software engineering practice.

The main issue is that **get** and **upsert** methods in the trait accept generic type parameters. My first attempt was to get rid of these generic type parameters.

For **get** method, it's possible, even though it deviates from the common signature of **get** in rust collections and makes its usage scenarios more limited. Here is the result:

```
pub trait Map<K: Sync, V> {
    fn put(&mut self, k: K, v: V) -> Option<V>;
    fn upsert<U: Fn(&mut V)>(&self, key: K, value: V, updater: &U);
    fn get(&self, k: &K) -> Option<V>;
    // other methods ommited for brevity
}

```

However, I do not have any idea about the way to remove the generic type parameter in **upsert**.

Any idea on how to deal with this issue?