Problem with HashMap.get and match

I have a problem getting the types correct. This code shows the problem:

use std::collections::HashMap;

struct Inner {
    x: usize
}

struct Outer {
    internals: HashMap<String, Inner>,
}

fn test() {
    let outer = Outer {
	internals: vec![("inner".to_string(),
		     Inner { x: 20 })]
	    .into_iter()
	    .collect()
    };
    match outer.internals.get("inner") {
	None => {},
	Some(inner) => {
	    inner.x += 1;
	}
    }
}

This does not compile. I get the error:

error[E0594]: cannot assign to `inner.x` which is behind a `&` reference
  --> src/lib.rs:21:6
   |
20 |     Some(inner) => {
   |          ----- help: consider changing this to be a mutable reference: `&mut Inner`
21 |         inner.x += 1;
   |         ^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be written

Doing the suggested change does not help either. Some(&mut inner) produces this error:

error[E0308]: mismatched types
  --> src/lib.rs:20:7
   |
18 |     match outer.internals.get("inner") {
   |           ---------------------------- this expression has type `Option<&Inner>`
19 |     None => {},
20 |     Some(&mut inner) => {
   |          ^^^^^^^^^^
   |          |
   |          types differ in mutability
   |          help: you can probably remove the explicit borrow: `inner`
   |
   = note:      expected reference `&Inner`
           found mutable reference `&mut _`

How should I define the match handles? Or is there something else that needs to be fixed?

Use get_mut instead of get

2 Likes

Thanks! It needs let mut outer = ... too. Below is the working version.

use std::collections::HashMap;

struct Inner {
    x: usize
}

struct Outer {
    internals: HashMap<String, Inner>,
}

fn test() {
    let mut outer = Outer {
	internals: vec![("inner".to_string(),
		     Inner { x: 20 })]
	    .into_iter()
	    .collect()
    };
    match outer.internals.get_mut("inner") {
	None => {},
	Some(inner) => {
	    inner.x += 1;
	}
    }
}