about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-03-19 18:03:51 +0100
committerGitHub <noreply@github.com>2024-03-19 18:03:51 +0100
commit17386b8fbfa876c1dc4355d7d166c5567974825b (patch)
tree6dcf123a873a99f3a4a773c592d477744cb81256
parent42dec6f874c81fd1a6c72f05a8dc439916669bc7 (diff)
parent19f72dfe04d030aba3885333156590d0b9191851 (diff)
downloadrust-17386b8fbfa876c1dc4355d7d166c5567974825b.tar.gz
rust-17386b8fbfa876c1dc4355d7d166c5567974825b.zip
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
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs37
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--tests/ui/pattern/patkind-ref-binding-issue-114896.fixed10
-rw-r--r--tests/ui/pattern/patkind-ref-binding-issue-114896.rs (renamed from tests/ui/pattern/issue-114896.rs)3
-rw-r--r--tests/ui/pattern/patkind-ref-binding-issue-114896.stderr (renamed from tests/ui/pattern/issue-114896.stderr)2
-rw-r--r--tests/ui/pattern/patkind-ref-binding-issue-122415.fixed11
-rw-r--r--tests/ui/pattern/patkind-ref-binding-issue-122415.rs11
-rw-r--r--tests/ui/pattern/patkind-ref-binding-issue-122415.stderr11
8 files changed, 71 insertions, 15 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index a27d016e0ba..36c2723b66d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -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;
@@ -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)
         {
@@ -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 {
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 03e4ecca9d6..5b4ef4e93dd 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -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",
diff --git a/tests/ui/pattern/patkind-ref-binding-issue-114896.fixed b/tests/ui/pattern/patkind-ref-binding-issue-114896.fixed
new file mode 100644
index 00000000000..086a119eb77
--- /dev/null
+++ b/tests/ui/pattern/patkind-ref-binding-issue-114896.fixed
@@ -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
+    }
+}
diff --git a/tests/ui/pattern/issue-114896.rs b/tests/ui/pattern/patkind-ref-binding-issue-114896.rs
index cde37f658d6..b4d6b72c01f 100644
--- a/tests/ui/pattern/issue-114896.rs
+++ b/tests/ui/pattern/patkind-ref-binding-issue-114896.rs
@@ -1,3 +1,6 @@
+//@ run-rustfix
+#![allow(dead_code)]
+
 fn main() {
     fn x(a: &char) {
         let &b = a;
diff --git a/tests/ui/pattern/issue-114896.stderr b/tests/ui/pattern/patkind-ref-binding-issue-114896.stderr
index 285c9109e1b..68538255edd 100644
--- a/tests/ui/pattern/issue-114896.stderr
+++ b/tests/ui/pattern/patkind-ref-binding-issue-114896.stderr
@@ -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)`
diff --git a/tests/ui/pattern/patkind-ref-binding-issue-122415.fixed b/tests/ui/pattern/patkind-ref-binding-issue-122415.fixed
new file mode 100644
index 00000000000..6144f062169
--- /dev/null
+++ b/tests/ui/pattern/patkind-ref-binding-issue-122415.fixed
@@ -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() {}
diff --git a/tests/ui/pattern/patkind-ref-binding-issue-122415.rs b/tests/ui/pattern/patkind-ref-binding-issue-122415.rs
new file mode 100644
index 00000000000..b9f6416027a
--- /dev/null
+++ b/tests/ui/pattern/patkind-ref-binding-issue-122415.rs
@@ -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() {}
diff --git a/tests/ui/pattern/patkind-ref-binding-issue-122415.stderr b/tests/ui/pattern/patkind-ref-binding-issue-122415.stderr
new file mode 100644
index 00000000000..39283133ac7
--- /dev/null
+++ b/tests/ui/pattern/patkind-ref-binding-issue-122415.stderr
@@ -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`.