-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Description
Code
struct S {
a: Vec<i32>,
b: i32,
}
impl S {
fn helper(&mut self) {
// does something that requires &mut self
self.b += 1;
}
fn f(&mut self) {
let x = self.a.get(0); // immutable borrow of part of self
// Attempt to use &mut self while the immutable borrow is still live
self.helper();
// Keeps the immutable borrow alive
if let Some(v) = x {
println!("{}", v);
}
}
}Current output
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/compiler_error_message_issue.rs:16:9
|
13 | let x = self.a.get(0); // immutable borrow of part of self
| ------ immutable borrow occurs here
...
16 | self.helper();
| ^^^^^^^^^^^^^ mutable borrow occurs here
...
19 | if let Some(v) = x {
| - immutable borrow later used hereDesired output
error[E0502]: cannot use mutable borrow of `self` because a part of it is borrowed as immutable.
--> src/compiler_error_message_issue.rs:16:9
|
13 | let x = self.a.get(0); // immutable borrow of part of self
| ------ immutable borrow occurs here
...
16 | self.helper();
| ^^^^^^^^^^^^^ use of mutable borrow occurs here
...
19 | if let Some(v) = x {
| - immutable borrow later used hereRationale and extra context
I hope I'm not misinterpreting what "a borrow occuring" should be interpreted to mean across the board in rustc error messaging jargon, and under that disclaimer let me describe what I humbly find a little perhaps unnecessarily confusing:
- The error message describes the error as a failure to make a borrow.
- Yet to my understanding that borrow is already "live", since the function signature takes a mutable borrow of the same (the
self).
So I'm not sure why it says "mutable borrow occurs here" about line 16, and why the heading of the error says "cannot borrow".
Rather, they can perhaps say respectively:
use of mutable borrow occurs here
cannot use mutable borrow of
selfbecause a part of it is borrowed as immutable.
I just find it somewhat perhaps under-specified to call it "borrow" rather than "use borrow".
This here assumes, perhaps wrongly (?!) that a borrow stays live, if I can use that word, until the compiler has deemed that it no longer is, in which case it's not a new borrow when being used at a point (line 16) which is after its become alive (which in my example above, happens if I'm again not wrong, at entry into the function f due to its &mut self signature definition in line 12).
I apologize in case there's a far reaching convention about calling borrows and use of them as always just "borrows", or in case my mental model at 3 months deep into rust with a lot of ChatGPT 5.2 conversation is lacking.
Is it the case that when a signature has &mut self (or any other argument not just self) then the borrow only starts on its first use? I doubt that since I presume that callers of f seem to be aware that it takes a mutable borrow of self, but ...
Is it conversely just the case that the mutable borrow of line 12 ends at line 13 and hence line 16 is really a new &mut borrow of self?
Second issue I have with feeling at ease with the message is that it says that self is "also borrowed as immutable" whereas only its field a is.
A related issue on that last asepct is #147108, which I'm not sure is exactly the same, since in theirs, they use a getter which actually borrows all of self which my example does not! In my example it's to the best of my judgement and GPT-5.2's a borrow of only the field (a.k.a partial borrow).
Other cases
Rust Version
rustc --version --verbose
rustc 1.94.0 (4a4ef493e 2026-03-02)
binary: rustc
commit-hash: 4a4ef493e3a1488c6e321570238084b38948f6db
commit-date: 2026-03-02
host: x86_64-unknown-linux-gnu
release: 1.94.0
LLVM version: 21.1.8Anything else?
Thank you for the overall quality of error messages.