Pattern matching causes problems with borrow checker

I can't quite get why the first example of code compiles, and the second one complains that unpacking in match can't borrow a value as mutable behind a & reference.

This code compiles.

match self.elt {
	None => Err("<tag> outside of node/way/relation".into()),
	Some(OsmObj::Node(ref mut n)) => {
		let (k, v) = get_tag(&self.rd, &e)?;
		n.tags.push(k, v);
		Ok(None)
	},
	Some(OsmObj::Way(ref mut w)) => {
		let (k, v) = get_tag(&self.rd, &e)?;
		w.tags.push(k, v);
		Ok(None)
	}
}

This does not. No matter how many ref mut and & you add around osmobj.

match &self.elt {
	None => Err("<tag> outside of node/way/relation".into()),
	Some(osmobj) => { // adding ref mut won't help
		let (k, v) = get_tag(&self.rd, &e)?;
		match osmobj { // adding &/&mut won't help
			OsmObj::Node(ref mut n) => n.tags.push(k, v),  // here, n can't be borrowed as mutable
			OsmObj::Way(ref mut w) => w.tags.push(k, v),  // here, w can't be borrowed as mutable
		}
		Ok(None)
	}
}

I've found this question which seems similar. I can just guess that it's because match osmobj moves osmobj and makes it's lifetime last not till the end of the function.

Any ideas?

The problem is this line:

match &self.elt {

Since you are matching on an immutable reference, anything derived from it cannot be used to modify stuff.

1 Like

Oh god, this one is the only I didn't try to change! Thanks!