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
This commit is contained in:
parent
21d94a3d2c
commit
19f72dfe04
8 changed files with 71 additions and 15 deletions
|
@ -2,7 +2,7 @@
|
||||||
#![allow(rustc::untranslatable_diagnostic)]
|
#![allow(rustc::untranslatable_diagnostic)]
|
||||||
|
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
use hir::ExprKind;
|
use hir::{ExprKind, Param};
|
||||||
use rustc_errors::{Applicability, Diag};
|
use rustc_errors::{Applicability, Diag};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
|
@ -725,25 +725,26 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
_ => local_decl.source_info.span,
|
_ => 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
|
// With ref-binding patterns, the mutability suggestion has to apply to
|
||||||
// the binding, not the reference (which would be a type error):
|
// the binding, not the reference (which would be a type error):
|
||||||
//
|
//
|
||||||
// `let &b = a;` -> `let &(mut b) = a;`
|
// `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 {
|
&& let hir::Node::Local(hir::Local {
|
||||||
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
|
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) =
|
&& let Ok(name) =
|
||||||
self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
|
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)
|
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 {
|
pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
|
||||||
|
|
|
@ -3463,7 +3463,6 @@
|
||||||
"ui/pattern/issue-106552.rs",
|
"ui/pattern/issue-106552.rs",
|
||||||
"ui/pattern/issue-106862.rs",
|
"ui/pattern/issue-106862.rs",
|
||||||
"ui/pattern/issue-110508.rs",
|
"ui/pattern/issue-110508.rs",
|
||||||
"ui/pattern/issue-114896.rs",
|
|
||||||
"ui/pattern/issue-115599.rs",
|
"ui/pattern/issue-115599.rs",
|
||||||
"ui/pattern/issue-11577.rs",
|
"ui/pattern/issue-11577.rs",
|
||||||
"ui/pattern/issue-117626.rs",
|
"ui/pattern/issue-117626.rs",
|
||||||
|
|
10
tests/ui/pattern/patkind-ref-binding-issue-114896.fixed
Normal file
10
tests/ui/pattern/patkind-ref-binding-issue-114896.fixed
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,6 @@
|
||||||
|
//@ run-rustfix
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
fn x(a: &char) {
|
fn x(a: &char) {
|
||||||
let &b = a;
|
let &b = a;
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
|
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;
|
LL | let &b = a;
|
||||||
| -- help: consider changing this to be mutable: `&(mut b)`
|
| -- help: consider changing this to be mutable: `&(mut b)`
|
11
tests/ui/pattern/patkind-ref-binding-issue-122415.fixed
Normal file
11
tests/ui/pattern/patkind-ref-binding-issue-122415.fixed
Normal file
|
@ -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
tests/ui/pattern/patkind-ref-binding-issue-122415.rs
Normal file
11
tests/ui/pattern/patkind-ref-binding-issue-122415.rs
Normal file
|
@ -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
tests/ui/pattern/patkind-ref-binding-issue-122415.stderr
Normal file
11
tests/ui/pattern/patkind-ref-binding-issue-122415.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue