Skip to content

Commit

Permalink
Unrolled build for rust-lang#122677
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#122677 - surechen:fix_122415, r=Nadrieril

Fix incorrect mutable suggestion information for binding in ref pattern.

For ref pattern in func param, the mutability suggestion has to apply to the binding.

For example: `fn foo(&x: &i32)` -> `fn foo(&(mut x): &i32)`

fixes rust-lang#122415
  • Loading branch information
rust-timer authored Mar 19, 2024
2 parents a385e56 + 19f72df commit 2c9db35
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 15 deletions.
37 changes: 24 additions & 13 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![allow(rustc::untranslatable_diagnostic)]

use core::ops::ControlFlow;
use hir::ExprKind;
use hir::{ExprKind, Param};
use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
Expand Down Expand Up @@ -725,25 +725,26 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
_ => local_decl.source_info.span,
};

let def_id = self.body.source.def_id();
let hir_id = if let Some(local_def_id) = def_id.as_local()
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
{
let body = self.infcx.tcx.hir().body(body_id);
BindingFinder { span: pat_span }.visit_body(body).break_value()
} else {
None
};

// With ref-binding patterns, the mutability suggestion has to apply to
// the binding, not the reference (which would be a type error):
//
// `let &b = a;` -> `let &(mut b) = a;`
if let Some(hir_id) = hir_id
// or
// `fn foo(&x: &i32)` -> `fn foo(&(mut x): &i32)`
let def_id = self.body.source.def_id();
if let Some(local_def_id) = def_id.as_local()
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
&& let body = self.infcx.tcx.hir().body(body_id)
&& let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(body).break_value()
&& let node = self.infcx.tcx.hir_node(hir_id)
&& let hir::Node::Local(hir::Local {
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
..
}) = self.infcx.tcx.hir_node(hir_id)
})
| hir::Node::Param(Param {
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
..
}) = node
&& let Ok(name) =
self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
{
Expand Down Expand Up @@ -1310,6 +1311,16 @@ impl<'tcx> Visitor<'tcx> for BindingFinder {
hir::intravisit::walk_stmt(self, s)
}
}

fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) -> Self::Result {
if let hir::Pat { kind: hir::PatKind::Ref(_, _), span, .. } = param.pat
&& *span == self.span
{
ControlFlow::Break(param.hir_id)
} else {
ControlFlow::Continue(())
}
}
}

pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
Expand Down
1 change: 0 additions & 1 deletion src/tools/tidy/src/issues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3463,7 +3463,6 @@
"ui/pattern/issue-106552.rs",
"ui/pattern/issue-106862.rs",
"ui/pattern/issue-110508.rs",
"ui/pattern/issue-114896.rs",
"ui/pattern/issue-115599.rs",
"ui/pattern/issue-11577.rs",
"ui/pattern/issue-117626.rs",
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/pattern/patkind-ref-binding-issue-114896.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//@ run-rustfix
#![allow(dead_code)]

fn main() {
fn x(a: &char) {
let &(mut b) = a;
b.make_ascii_uppercase();
//~^ cannot borrow `b` as mutable, as it is not declared as mutable
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//@ run-rustfix
#![allow(dead_code)]

fn main() {
fn x(a: &char) {
let &b = a;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
--> $DIR/issue-114896.rs:4:9
--> $DIR/patkind-ref-binding-issue-114896.rs:7:9
|
LL | let &b = a;
| -- help: consider changing this to be mutable: `&(mut b)`
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/pattern/patkind-ref-binding-issue-122415.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//@ run-rustfix
#![allow(dead_code)]

fn mutate(_y: &mut i32) {}

fn foo(&(mut x): &i32) {
mutate(&mut x);
//~^ ERROR cannot borrow `x` as mutable
}

fn main() {}
11 changes: 11 additions & 0 deletions tests/ui/pattern/patkind-ref-binding-issue-122415.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//@ run-rustfix
#![allow(dead_code)]

fn mutate(_y: &mut i32) {}

fn foo(&x: &i32) {
mutate(&mut x);
//~^ ERROR cannot borrow `x` as mutable
}

fn main() {}
11 changes: 11 additions & 0 deletions tests/ui/pattern/patkind-ref-binding-issue-122415.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
--> $DIR/patkind-ref-binding-issue-122415.rs:7:12
|
LL | fn foo(&x: &i32) {
| -- help: consider changing this to be mutable: `&(mut x)`
LL | mutate(&mut x);
| ^^^^^^ cannot borrow as mutable

error: aborting due to 1 previous error

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

0 comments on commit 2c9db35

Please sign in to comment.