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 gives E0499 in loops with mutable borrows, but it is misleading #99824

Closed
TheButlah opened this issue Jul 27, 2022 · 2 comments · Fixed by #102080
Closed

Borrow checker gives E0499 in loops with mutable borrows, but it is misleading #99824

TheButlah opened this issue Jul 27, 2022 · 2 comments · Fixed by #102080
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@TheButlah
Copy link

TheButlah commented Jul 27, 2022

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6a4dbffaa1c7bfe6e167b40eacaca921
The current output is:

error[E0499]: cannot borrow `decoder` as mutable more than once at a time
  --> src/main.rs:15:29
   |
15 |     while let Some(frame) = decoder.read_next_frame().unwrap() {
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^ `decoder` was mutably borrowed here in the previous iteration of the loop

It looks like the error is pointing to the wrong spot in the code and is quite misleading.
Ideally the output should mention that decoder is still mutably borrowed because it holds a reference to frame between loops. Or something, im not actually sure :P

I have confirmed that this occurs in both the latest stable (1.62.1) and nightly (1.64.0-nightly 4d6d601c8 2022-07-26)

@TheButlah TheButlah added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 27, 2022
@yanchen4791
Copy link
Contributor

@rustbot claim

@yanchen4791
Copy link
Contributor

With the proposed fix #102080, the output will be like this:

error[E0499]: cannot borrow `decoder` as mutable more than once at a time
  --> main.rs:15:29
   |
15 |     while let Some(frame) = decoder.read_next_frame().unwrap() {
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^ `decoder` was mutably borrowed here in the previous iteration of the loop
16 |         frames.push(frame);  // this line is the culprit
   |         ------------------ first borrow later used here

error: aborting due to previous error

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Oct 15, 2022
…illot

Fix missing explanation of where the borrowed reference is used when the same borrow occurs multiple times due to loop iterations

Fix rust-lang#99824.

Problem of the issue:
If a borrow occurs in a loop, the borrowed reference could be invalidated at the same place at next iteration of the loop. When this happens, the point where the borrow occurs is the same as the intervening point that might invalidate the reference in the loop. This causes a problem for the current code finding the point where the resulting reference is used, so that the explanation of the cause will be missing. As the second point of "explain all errors in terms of three points" (see [leveraging intuition framing errors in terms of points"](https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points), this explanation is very helpful for user to understand the error.

In the current implementation, the searching region for finding the location where the borrowed reference is used is limited to between the place where the borrow occurs and the place where the reference is invalidated. If those two places happen to be the same, which indicates that the borrow and invalidation occur at the same place in a loop, the search will fail.

One solution to the problem is when these two places are the same,  find the terminator of the loop, and then use the location of the loop terminator instead of the location of the borrow for the region to find the place where the borrowed reference is used.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Oct 15, 2022
…illot

Fix missing explanation of where the borrowed reference is used when the same borrow occurs multiple times due to loop iterations

Fix rust-lang#99824.

Problem of the issue:
If a borrow occurs in a loop, the borrowed reference could be invalidated at the same place at next iteration of the loop. When this happens, the point where the borrow occurs is the same as the intervening point that might invalidate the reference in the loop. This causes a problem for the current code finding the point where the resulting reference is used, so that the explanation of the cause will be missing. As the second point of "explain all errors in terms of three points" (see [leveraging intuition framing errors in terms of points"](https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points), this explanation is very helpful for user to understand the error.

In the current implementation, the searching region for finding the location where the borrowed reference is used is limited to between the place where the borrow occurs and the place where the reference is invalidated. If those two places happen to be the same, which indicates that the borrow and invalidation occur at the same place in a loop, the search will fail.

One solution to the problem is when these two places are the same,  find the terminator of the loop, and then use the location of the loop terminator instead of the location of the borrow for the region to find the place where the borrowed reference is used.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Oct 15, 2022
…illot

Fix missing explanation of where the borrowed reference is used when the same borrow occurs multiple times due to loop iterations

Fix rust-lang#99824.

Problem of the issue:
If a borrow occurs in a loop, the borrowed reference could be invalidated at the same place at next iteration of the loop. When this happens, the point where the borrow occurs is the same as the intervening point that might invalidate the reference in the loop. This causes a problem for the current code finding the point where the resulting reference is used, so that the explanation of the cause will be missing. As the second point of "explain all errors in terms of three points" (see [leveraging intuition framing errors in terms of points"](https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points), this explanation is very helpful for user to understand the error.

In the current implementation, the searching region for finding the location where the borrowed reference is used is limited to between the place where the borrow occurs and the place where the reference is invalidated. If those two places happen to be the same, which indicates that the borrow and invalidation occur at the same place in a loop, the search will fail.

One solution to the problem is when these two places are the same,  find the terminator of the loop, and then use the location of the loop terminator instead of the location of the borrow for the region to find the place where the borrowed reference is used.
bors added a commit to rust-lang-ci/rust that referenced this issue Oct 16, 2022
Fix missing explanation of where the borrowed reference is used when the same borrow occurs multiple times due to loop iterations

Fix rust-lang#99824.

Problem of the issue:
If a borrow occurs in a loop, the borrowed reference could be invalidated at the same place at next iteration of the loop. When this happens, the point where the borrow occurs is the same as the intervening point that might invalidate the reference in the loop. This causes a problem for the current code finding the point where the resulting reference is used, so that the explanation of the cause will be missing. As the second point of "explain all errors in terms of three points" (see [leveraging intuition framing errors in terms of points"](https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points), this explanation is very helpful for user to understand the error.

In the current implementation, the searching region for finding the location where the borrowed reference is used is limited to between the place where the borrow occurs and the place where the reference is invalidated. If those two places happen to be the same, which indicates that the borrow and invalidation occur at the same place in a loop, the search will fail.

One solution to the problem is when these two places are the same,  find the terminator of the loop, and then use the location of the loop terminator instead of the location of the borrow for the region to find the place where the borrowed reference is used.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
2 participants