Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Borrow checker allows multiple mutable references in the same scope (unexpected behavior) #138140

Closed
dgl-prc opened this issue Mar 7, 2025 · 3 comments

Comments

@dgl-prc
Copy link

dgl-prc commented Mar 7, 2025

Accoring to Rust’s borrowing rules, there shouldn't be more than one mutable reference in the same scope, but in the followin code it actually compiled and executed successfully.

I tried this code:

fn main() {
    let mut x = 1;
    let y = &mut x;
    let z = &mut x;
    println!("{}", x);
}

I expected to see this happen: *error[E0499]: cannot borrow x as mutable more than once at a time
*

Instead, this happened: it actually compiled and executed successfully,and only raises two warnings of "warning: unused variable"

Meta

rustc --version --verbose:

rustc 1.85.0 (4d91de4e4 2025-02-17)
binary: rustc
commit-hash: 4d91de4e48198da2e33413efdcd9cd2cc0c46688
commit-date: 2025-02-17
host: aarch64-apple-darwin
release: 1.85.0
LLVM version: 19.1.7
Backtrace

warning: unused variable: `y`
 --> src/main.rs:3:9
  |
3 |     let y = &mut x;
  |         ^ help: if this is intentional, prefix it with an underscore: `_y`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `z`
 --> src/main.rs:4:9
  |
4 |     let z = &mut x;
  |         ^ help: if this is intentional, prefix it with an underscore: `_z`

warning: `rust_exercise` (bin "rust_exercise") generated 2 warnings
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s

@dgl-prc dgl-prc added the C-bug Category: This is a bug. label Mar 7, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Mar 7, 2025
@moxian
Copy link
Contributor

moxian commented Mar 7, 2025

This is intentional.
Rustc used to error out as you suggest prior to 1.35.0 release (godbolt) but that was a major source of frustration and got changed, to everyone's delight.

You can read more about the problem and the solution in the Non-Lexical Lifetimes RFC - https://rust-lang.github.io/rfcs/2094-nll.html

(technically, NLL only partially shipped in 1.35.0. The full release was in 1.65.0)

@moxian
Copy link
Contributor

moxian commented Mar 7, 2025

Also note this bit in rust book, which explains this (https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#mutable-references):

Note that a reference’s scope starts from where it is introduced and continues through the last time that reference is used. For instance, this code will compile because the last usage of the immutable references is in the println!, before the mutable reference is introduced:

let mut s = String::from("hello");

let r1 = &s; // no problem
let r2 = &s; // no problem
println!("{r1} and {r2}");
// variables r1 and r2 will not be used after this point

let r3 = &mut s; // no problem
println!("{r3}");

The scopes of the immutable references r1 and r2 end after the println! where they are last used, which is before the mutable reference r3 is created. These scopes don’t overlap, so this code is allowed: the compiler can tell that the reference is no longer being used at a point before the end of the scope.

@dgl-prc
Copy link
Author

dgl-prc commented Mar 7, 2025

Thank you.

@dgl-prc dgl-prc closed this as completed Mar 7, 2025
@jieyouxu jieyouxu removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Mar 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants