The compiler is telling me a method doesn't exist and I'm sure it does

I'm trying to concurrently access two different properties in a serde_json Object.
The first way I went is to use the splitmut crate but it wasn't implemented on serde_json Map, so I forked it.
And I got this error:
no method named `get_mut` found for type `&mut serde_json::Map<String, serde_json::Value>` in the current scope

I have no clue anymore. every trait bound is looking right.
I'm dumping all code I added.

cargo.toml:

[dependencies]
serde_json = "1.0"

lib.rs:

extern crate serde_json;

unsafe impl<'a, String: borrow::Borrow<Q>, Q: Ord + Eq + hash::Hash + ?Sized> SplitMut<&'a Q, serde_json::Value> for serde_json::Map<String, serde_json::Value> {
    #[inline]
    fn get1_mut(&mut self, k: &'a Q) -> Option<&mut serde_json::Value> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: &'a Q) -> &mut serde_json::Value { std::mem::transmute(self.get_mut(k)) }
}

What is wrong in here? is there a better approach to do this?

In this code, String is not the standard library's std::string::String type, but a new type parameter you have declared that happens to have the same name:

unsafe impl<'a, String: borrow::Borrow<Q>, Q: Ord + Eq + hash::Hash + ?Sized>

but to use get_mut you need to use the standard String type, not a generic type variable named String. Something like this should work:

unsafe impl<'a, Q> SplitMut<&'a Q, serde_json::Value>
for serde_json::Map<String, serde_json::Value>
where
    String: borrow::Borrow<Q>,
    Q: Ord + Eq + hash::Hash + ?Sized
1 Like

Oh, I heard where clause was just syntactic sugar for long generic definition but apparently there are situation where it's necessary? anyway that's super helpful for saving my night. thanks!

Yes, where clauses can express things that can't be expressed in the parameter list, like bounds on types that are not generic parameters.

2 Likes