-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Open
Labels
A-borrow-checkerArea: The borrow checkerArea: The borrow checkerC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.fixed-by-poloniusCompiling with `-Zpolonius` fixes this issue.Compiling with `-Zpolonius` fixes this issue.
Description
When trying to mutate a value within a match statement which is borrowed by the statement and returned as the result of the function, the compiler fails with the error E0506.
I tried this code:
struct LazyItem {
item: Option<String>
}
impl LazyItem {
fn get_item(&mut self) -> &str {
match &self.item {
None => {
self.item = Some("Greetings".to_string());
let Some(content) = &self.item else { unreachable!() };
content
},
Some(content) => content,
}
}
}
fn main() {
let mut instance = LazyItem { item: None };
assert_eq!(instance.get_item(), "Greetings");
}I expected to see this happen: That the code compiles and runs successfully.
Instead, this happened: The compilation failed with the following error:
error[E0506]: cannot assign to `self.item` because it is borrowed
--> src/main.rs:9:17
|
6 | fn get_item(&mut self) -> &str {
| - let's call the lifetime of this reference `'1`
7 | match &self.item {
| - ---------- `self.item` is borrowed here
| _________|
| |
8 | | None => {
9 | | self.item = Some("Greetings".to_string());
| | ^^^^^^^^^ `self.item` is assigned to here but it was already borrowed
10 | | let Some(content) = &self.item else { unreachable!() };
... |
13 | | Some(content) => content,
14 | | }
| |_________- returning this value requires that `self.item` is borrowed for `'1`
For more information about this error, try `rustc --explain E0506`.
Using if syntax the code compiles and runs successfully.
Code
struct LazyItem {
item: Option<String>
}
impl LazyItem {
fn get_item(&mut self) -> &str {
if let None = &self.item {
self.item = Some("Greetings".to_string());
let Some(content) = &self.item else { unreachable!() };
content
} else if let Some(content) = &self.item {
content
} else {
unreachable!()
}
}
}
fn main() {
let mut instance = LazyItem { item: None };
assert_eq!(instance.get_item(), "Greetings");
}Meta
rustc --version --verbose:
rustc 1.72.0 (5680fa18f 2023-08-23)
binary: rustc
commit-hash: 5680fa18feaa87f3ff04063800aec256c3d4b4be
commit-date: 2023-08-23
host: x86_64-unknown-linux-gnu
release: 1.72.0
LLVM version: 16.0.5
Nigthly version with the same result:
rustc 1.74.0-nightly (4e78abb43 2023-08-28)
binary: rustc
commit-hash: 4e78abb437a0478d1f42115198ee45888e5330fd
commit-date: 2023-08-28
host: x86_64-unknown-linux-gnu
release: 1.74.0-nightly
LLVM version: 17.0.0
Metadata
Metadata
Assignees
Labels
A-borrow-checkerArea: The borrow checkerArea: The borrow checkerC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.fixed-by-poloniusCompiling with `-Zpolonius` fixes this issue.Compiling with `-Zpolonius` fixes this issue.