diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3e2c2e8cc3944..b32522448f0d6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -3012,6 +3012,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false, )); } + ( + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, inner), + &ty::Ref(_, exp_inner, hir::Mutability::Mut), + &ty::Ref(_, check_inner, hir::Mutability::Not), + ) if { + let new_mut_ref = + Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, check_inner); + self.may_coerce(new_mut_ref, expected) + || self.can_eq(self.param_env, check_inner, exp_inner) + } => + { + let inner_span = inner.span.find_ancestor_inside(sp).unwrap_or(inner.span); + if sp.contains(inner_span) && sm.is_span_accessible(inner_span) { + let borrow_span = sp.until(inner_span); + return Some(( + vec![(borrow_span, "&mut ".to_string())], + "change the borrow to be mutable".to_string(), + Applicability::MachineApplicable, + false, + )); + } + } (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (exp.kind(), check.kind()) { (&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.kind diff --git a/tests/ui/suggestions/suggest-changing-argument-mutability.rs b/tests/ui/suggestions/suggest-changing-argument-mutability.rs new file mode 100644 index 0000000000000..02e27bd3ed3ab --- /dev/null +++ b/tests/ui/suggestions/suggest-changing-argument-mutability.rs @@ -0,0 +1,16 @@ +fn takes_mut(_: &mut String) {} + +struct S; +impl S { + fn mutate(&mut self, _: &mut i32) {} +} + +fn main() { + let mut s = String::new(); + takes_mut(&s); + //~^ ERROR mismatched types + + let mut val = 42; + S.mutate(&val); + //~^ ERROR mismatched types +} diff --git a/tests/ui/suggestions/suggest-changing-argument-mutability.stderr b/tests/ui/suggestions/suggest-changing-argument-mutability.stderr new file mode 100644 index 0000000000000..5e56d3196d68f --- /dev/null +++ b/tests/ui/suggestions/suggest-changing-argument-mutability.stderr @@ -0,0 +1,43 @@ +error[E0308]: mismatched types + --> $DIR/suggest-changing-argument-mutability.rs:10:15 + | +LL | takes_mut(&s); + | --------- ^^ types differ in mutability + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut String` + found reference `&String` +note: function defined here + --> $DIR/suggest-changing-argument-mutability.rs:1:4 + | +LL | fn takes_mut(_: &mut String) {} + | ^^^^^^^^^ ------------------ +help: change the borrow to be mutable + | +LL | takes_mut(&mut s); + | +++ + +error[E0308]: mismatched types + --> $DIR/suggest-changing-argument-mutability.rs:14:14 + | +LL | S.mutate(&val); + | ------ ^^^^ types differ in mutability + | | + | arguments to this method are incorrect + | + = note: expected mutable reference `&mut i32` + found reference `&i32` +note: method defined here + --> $DIR/suggest-changing-argument-mutability.rs:5:8 + | +LL | fn mutate(&mut self, _: &mut i32) {} + | ^^^^^^ ----------------------- +help: change the borrow to be mutable + | +LL | S.mutate(&mut val); + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. \ No newline at end of file