Skip to content

Commit 17386b8

Browse files
authored
Rollup merge of #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 #122415
2 parents 42dec6f + 19f72df commit 17386b8

8 files changed

+71
-15
lines changed

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+24-13
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![allow(rustc::untranslatable_diagnostic)]
33

44
use core::ops::ControlFlow;
5-
use hir::ExprKind;
5+
use hir::{ExprKind, Param};
66
use rustc_errors::{Applicability, Diag};
77
use rustc_hir as hir;
88
use rustc_hir::intravisit::Visitor;
@@ -725,25 +725,26 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
725725
_ => local_decl.source_info.span,
726726
};
727727

728-
let def_id = self.body.source.def_id();
729-
let hir_id = if let Some(local_def_id) = def_id.as_local()
730-
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
731-
{
732-
let body = self.infcx.tcx.hir().body(body_id);
733-
BindingFinder { span: pat_span }.visit_body(body).break_value()
734-
} else {
735-
None
736-
};
737-
738728
// With ref-binding patterns, the mutability suggestion has to apply to
739729
// the binding, not the reference (which would be a type error):
740730
//
741731
// `let &b = a;` -> `let &(mut b) = a;`
742-
if let Some(hir_id) = hir_id
732+
// or
733+
// `fn foo(&x: &i32)` -> `fn foo(&(mut x): &i32)`
734+
let def_id = self.body.source.def_id();
735+
if let Some(local_def_id) = def_id.as_local()
736+
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
737+
&& let body = self.infcx.tcx.hir().body(body_id)
738+
&& let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(body).break_value()
739+
&& let node = self.infcx.tcx.hir_node(hir_id)
743740
&& let hir::Node::Local(hir::Local {
744741
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
745742
..
746-
}) = self.infcx.tcx.hir_node(hir_id)
743+
})
744+
| hir::Node::Param(Param {
745+
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
746+
..
747+
}) = node
747748
&& let Ok(name) =
748749
self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
749750
{
@@ -1310,6 +1311,16 @@ impl<'tcx> Visitor<'tcx> for BindingFinder {
13101311
hir::intravisit::walk_stmt(self, s)
13111312
}
13121313
}
1314+
1315+
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) -> Self::Result {
1316+
if let hir::Pat { kind: hir::PatKind::Ref(_, _), span, .. } = param.pat
1317+
&& *span == self.span
1318+
{
1319+
ControlFlow::Break(param.hir_id)
1320+
} else {
1321+
ControlFlow::Continue(())
1322+
}
1323+
}
13131324
}
13141325

13151326
pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {

src/tools/tidy/src/issues.txt

-1
Original file line numberDiff line numberDiff line change
@@ -3463,7 +3463,6 @@
34633463
"ui/pattern/issue-106552.rs",
34643464
"ui/pattern/issue-106862.rs",
34653465
"ui/pattern/issue-110508.rs",
3466-
"ui/pattern/issue-114896.rs",
34673466
"ui/pattern/issue-115599.rs",
34683467
"ui/pattern/issue-11577.rs",
34693468
"ui/pattern/issue-117626.rs",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//@ run-rustfix
2+
#![allow(dead_code)]
3+
4+
fn main() {
5+
fn x(a: &char) {
6+
let &(mut b) = a;
7+
b.make_ascii_uppercase();
8+
//~^ cannot borrow `b` as mutable, as it is not declared as mutable
9+
}
10+
}

tests/ui/pattern/issue-114896.rs renamed to tests/ui/pattern/patkind-ref-binding-issue-114896.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//@ run-rustfix
2+
#![allow(dead_code)]
3+
14
fn main() {
25
fn x(a: &char) {
36
let &b = a;

tests/ui/pattern/issue-114896.stderr renamed to tests/ui/pattern/patkind-ref-binding-issue-114896.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
2-
--> $DIR/issue-114896.rs:4:9
2+
--> $DIR/patkind-ref-binding-issue-114896.rs:7:9
33
|
44
LL | let &b = a;
55
| -- help: consider changing this to be mutable: `&(mut b)`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//@ run-rustfix
2+
#![allow(dead_code)]
3+
4+
fn mutate(_y: &mut i32) {}
5+
6+
fn foo(&(mut x): &i32) {
7+
mutate(&mut x);
8+
//~^ ERROR cannot borrow `x` as mutable
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//@ run-rustfix
2+
#![allow(dead_code)]
3+
4+
fn mutate(_y: &mut i32) {}
5+
6+
fn foo(&x: &i32) {
7+
mutate(&mut x);
8+
//~^ ERROR cannot borrow `x` as mutable
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
2+
--> $DIR/patkind-ref-binding-issue-122415.rs:7:12
3+
|
4+
LL | fn foo(&x: &i32) {
5+
| -- help: consider changing this to be mutable: `&(mut x)`
6+
LL | mutate(&mut x);
7+
| ^^^^^^ cannot borrow as mutable
8+
9+
error: aborting due to 1 previous error
10+
11+
For more information about this error, try `rustc --explain E0596`.

0 commit comments

Comments
 (0)