Ah, that makes sense! Right, I completely missed that rustc
did that.
With the '1
lifetime, I think it's explicitly saying exactly what you did: that your return value has the same lifetime as &mut self
. I don't think it's really useful in this case, but in similar cases maybe it'd help more.
It's trying to help show why there are two mutable borrows at the same time. It tells you one of them explicitly: '1
is the lifetime of self
, and your return value must also have this lifetime, so thus self
is mutable borrowed from line 20 through the end of the function. Then it tells you the second borrow, which happens in the middle of this, and thus is a second mutable borrow.
I would argue it's more just the borrow checker doing its job right. This code would not be valid if it compiled - the rust compiler explicitly relies on function signatures to tell what things do, and a valid implementation of takes_mut_self
could cause bs
to be corrupted. This is what the borrow checker is supposed to prevent.
It is technically a limitation of the borrow checker that it can't look at takes_mut_self
and tell that it's safe or not. So you're not wrong! But since this is one of the common scenarios the borrow checker is designed to prevent, I think looking at regular lifetime documentation is probably more helpful than nomicon edge cases.
For instance, I think this error is pretty identical to the errors shown in chapter 4 of the book. You're borrowing self
rather than a random string s
, but the situation is otherwise identical to these two snippets:
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
and
let mut s = String::from("hello");
let r1 = &s; // no problem
let r2 = &s; // no problem
let r3 = &mut s; // BIG PROBLEM
println!("{}, {}, and {}", r1, r2, r3);
(more detail on these in the linked book chapter)