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

Closure captures immutable reference when mutable reference is necessary #87814

Closed
ldm0 opened this issue Aug 6, 2021 · 8 comments · Fixed by #88266
Closed

Closure captures immutable reference when mutable reference is necessary #87814

ldm0 opened this issue Aug 6, 2021 · 8 comments · Fixed by #88266
Assignees
Labels
A-closures Area: closures (`|args| { .. }`) C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@ldm0
Copy link
Contributor

ldm0 commented Aug 6, 2021

Code

I tried this code:

fn main() {
    let mut schema_all = vec![];
    (0..42).for_each(|_x| match Err(()) as Result<(), _> {
        Ok(()) => schema_all.push(()),
        Err(_) => (),
    });
}

I expected to see this happen: cargo build success

Instead, this happened: cargo build failed

error[E0596]: cannot borrow `schema_all` as mutable, as it is behind a `&` reference
 --> src/main.rs:4:19
  |
4 |         Ok(()) => schema_all.push(()),
  |                   ^^^^^^^^^^ cannot borrow as mutable

warning: variable does not need to be mutable
 --> src/main.rs:2:9
  |
2 |     let mut schema_all = vec![];
  |         ----^^^^^^^^^^
  |         |
  |         help: remove this `mut`
  |
  = note: `#[warn(unused_mut)]` on by default

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0596`.

Version it worked on

It most recently worked on: nightly-2021-03-16

Version with regression

rustc --version --verbose:

nightly-2021-03-17
@ldm0 ldm0 added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Aug 6, 2021
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Aug 6, 2021
@ldm0 ldm0 changed the title Closure capture immutable reference when mutable reference is necessary Closure captures immutable reference when mutable reference is necessary Aug 6, 2021
@jonas-schievink jonas-schievink added A-closures Area: closures (`|args| { .. }`) regression-from-stable-to-stable Performance or correctness regression from one stable version to another. and removed regression-untriaged Untriaged performance or correctness regression. labels Aug 6, 2021
@ldm0
Copy link
Contributor Author

ldm0 commented Aug 6, 2021

Regression in f5d8117 #82536

@LeSeulArtichaut
Copy link
Contributor

LeSeulArtichaut commented Aug 6, 2021

cc @roxelo @arora-aman @nikomatsakis

@roxelo
Copy link
Member

roxelo commented Aug 6, 2021

@rustbot claim

@roxelo
Copy link
Member

roxelo commented Aug 6, 2021

The issue appears to span from this line: return_if_err!(mc.cat_pattern(discr_place.clone(), &arm.pat, |place, pat| {.
mc.cat_pattern returns an error which leads us to return before we walk the arms of the match. As a result, we don't know that we need to capture schema_all as a mutable reference.

I am still investigating why cat_pattern returns an error

@roxelo
Copy link
Member

roxelo commented Aug 6, 2021

@LeSeulArtichaut I don't think this error is related to my changes anymore. I think my code instead led us to discover an ICE when as Result<(), _> is used. I think some work was done not so long ago on it.

For instance, these 2 code works:

fn main() {
    let mut schema_all = vec![];
    (0..42).for_each(|_x| match Err(()) { // removed as Result...
        Ok(()) => schema_all.push(()),
        Err(_) => (),
    });
}
fn main() {
    let mut schema_all = vec![];
    (0..42).for_each(|_x| match Err(()) as Result<(), _> {
        Ok(()) => schema_all.push(()),
        _ => (), // Use only _ here
    });
}

Otherwise, I took a look at why cat_pattern returns an error with the initial code snippet. When looking at the pattern Err(_) the cat_pattern returns an error here when unwrapping pat_ty_adjusted. This is because later on this function calls resolve_type_vars_or_error and ty.is_ty_var() here returns true.

In the meantime, a work around would be to first walk all of the arms of the match before trying to figure out whether the discreminent should be read or not. However, even with this fix, it is very likely that a similar issue would arise in the case that the discriminant also needs to be captured.

EDIT: In case we want to continue this conversation on zulip, I created a topic here: https://rust-lang.zulipchat.com/#narrow/stream/189812-t-compiler.2Fwg-rfc-2229/topic/Issue.20.2387814

@apiraino apiraino added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Aug 12, 2021
@roxelo
Copy link
Member

roxelo commented Aug 19, 2021

@rustbot label +A-edition-2021

@apiraino
Copy link
Contributor

apiraino commented Aug 19, 2021

Assigning priority as discussed in the Zulip thread of the Prioritization Working Group.

@rustbot label -I-prioritize +P-medium

EDIT: fixed link

@rustbot rustbot added P-medium Medium priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Aug 19, 2021
@m-ou-se m-ou-se added this to Stable Blockers in 2021 Edition Blockers Aug 23, 2021
@m-ou-se
Copy link
Member

m-ou-se commented Aug 23, 2021

(@apiraino That link links to the thread of another issue.)

@m-ou-se m-ou-se moved this from Stable Blockers to Migration crater run blockers in 2021 Edition Blockers Aug 23, 2021
@bors bors closed this as completed in b03ccac Aug 24, 2021
2021 Edition Blockers automation moved this from Migration crater run blockers to Completed items Aug 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-closures Area: closures (`|args| { .. }`) C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
2021 Edition Blockers
  
Completed items
7 participants