I tried to simplify my program, but there is no error if I use a simple HashMap<u16, u16>
instead of my nested HashMap
Polynome
class.
You will need these imports to reproduce the problem:
use std::collections::{HashMap, BTreeMap};
use std::hash::{Hash, Hasher};
These are my types:
pub struct VarIdx(pub BTreeMap<u16, u8>);
pub type Polynome = HashMap<VarIdx, f64>;
This is stuff I need to make the nested HashMap
work:
impl PartialEq for VarIdx {
fn eq(&self, other: &VarIdx) -> bool {
if self.0 == other.0 {
return true;
}
if self.0.len() != other.0.len() {
return false;
}
for (k, v) in self.0.iter() {
match other.0.get(k) {
Some(v1) => {
if v != v1 {
return false;
}
}
None => {}
}
}
(true)
}
}
impl Eq for VarIdx {}
impl VarIdx {
pub fn len(&self) -> usize {
return self.0.len();
}
}
impl Hash for VarIdx {
fn hash<H>(&self, _state: &mut H)
where
H: Hasher,
{
for (k, v) in self.0.iter() {
k.hash(_state);
v.hash(_state);
}
}
}
I have this function to find the first reasonable key:
fn get_first_product(poly: &Polynome) -> Option<&VarIdx> {
for (key, coeff) in poly {
if key.len() < 2 {
return None;
}
return Some(key);
}
None
}
I want to invoke this function and perform some manipulation based on returned key, for simplicity I want to remove this key from the HashMap
:
fn reduce_product(poly: &mut Polynome) -> bool {
let key = {
let res = get_first_product(poly);
if res == None {
return false;
}
res.unwrap()
};
poly.remove(&key);
true
}
This doesn't compile, because poly
is borrowed to get_first_product
and can't be reborrowed:
error[E0502]: cannot borrow `*poly` as mutable because it is also borrowed as immutable
--> src/main.rs:64:5
|
60 | let res = get_first_product(poly);
| ---- immutable borrow occurs here
...
64 | poly.remove(&key);
| ^^^^ mutable borrow occurs here
65 | true
66 | }
| - immutable borrow ends here
How can I solve this elementary task? I tried to .clone()
before passing poly
to get_first_product()
, but I get another error message:
error[E0599]: no method named `clone` found for type `&mut std::collections::HashMap<VarIdx, f64>` in the current scope
--> src/main.rs:65:42
|
65 | let res = get_first_product(poly.clone());
| ^^^^^
|
= note: the method `clone` exists but the following trait bounds were not satisfied:
`VarIdx : std::clone::Clone`
I have .clone()
implemented for VarIdx
.
What is recommended way to handle such case? I would like to avoid .clone
to have an efficient program.
This doesn't seem to be duplicate of this question, because if I try to use non-nested HashMap instead of Polynome, the code compiles fine:
fn get_first_product_nonnested(poly: &HashMap<u16, u16>) -> Option<u16> {
for (key, coeff) in poly {
if coeff>&2 {
return None;
}
return Some(*key);
}
None
}
fn reduce_product_nonnested(poly: &mut HashMap<u16,u16>) -> bool {
let key = {
let res = get_first_product_nonnested(poly);
if res == None { return false; }
res.unwrap()
};
poly.remove(&key);
true
}
So there is something, which makes my Polynome type different from HashMap.