diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index c77bbeb86e5..6e551e95cbb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -787,7 +787,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { _, [ Expr { - kind: MethodCall(path_segment, ..), + kind: + MethodCall( + path_segment, + _args, + span, + ), hir_id, .. }, @@ -831,7 +836,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(mut suggestions) = opt_suggestions { if suggestions.peek().is_some() { err.span_suggestions( - path_segment.ident.span, + *span, "use mutable method", suggestions, Applicability::MaybeIncorrect, diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index e0dbe027aef..9b37985ce49 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -299,52 +299,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { IsAssign::No => { let (message, missing_trait, use_output) = match op.node { hir::BinOpKind::Add => ( - format!("cannot add `{}` to `{}`", rhs_ty, lhs_ty), + format!("cannot add `{rhs_ty}` to `{lhs_ty}`"), Some("std::ops::Add"), true, ), hir::BinOpKind::Sub => ( - format!("cannot subtract `{}` from `{}`", rhs_ty, lhs_ty), + format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`"), Some("std::ops::Sub"), true, ), hir::BinOpKind::Mul => ( - format!("cannot multiply `{}` by `{}`", lhs_ty, rhs_ty), + format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`"), Some("std::ops::Mul"), true, ), hir::BinOpKind::Div => ( - format!("cannot divide `{}` by `{}`", lhs_ty, rhs_ty), + format!("cannot divide `{lhs_ty}` by `{rhs_ty}`"), Some("std::ops::Div"), true, ), hir::BinOpKind::Rem => ( - format!("cannot mod `{}` by `{}`", lhs_ty, rhs_ty), + format!("cannot mod `{lhs_ty}` by `{rhs_ty}`"), Some("std::ops::Rem"), true, ), hir::BinOpKind::BitAnd => ( - format!("no implementation for `{} & {}`", lhs_ty, rhs_ty), + format!("no implementation for `{lhs_ty} & {rhs_ty}`"), Some("std::ops::BitAnd"), true, ), hir::BinOpKind::BitXor => ( - format!("no implementation for `{} ^ {}`", lhs_ty, rhs_ty), + format!("no implementation for `{lhs_ty} ^ {rhs_ty}`"), Some("std::ops::BitXor"), true, ), hir::BinOpKind::BitOr => ( - format!("no implementation for `{} | {}`", lhs_ty, rhs_ty), + format!("no implementation for `{lhs_ty} | {rhs_ty}`"), Some("std::ops::BitOr"), true, ), hir::BinOpKind::Shl => ( - format!("no implementation for `{} << {}`", lhs_ty, rhs_ty), + format!("no implementation for `{lhs_ty} << {rhs_ty}`"), Some("std::ops::Shl"), true, ), hir::BinOpKind::Shr => ( - format!("no implementation for `{} >> {}`", lhs_ty, rhs_ty), + format!("no implementation for `{lhs_ty} >> {rhs_ty}`"), Some("std::ops::Shr"), true, ), @@ -477,8 +477,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // When we know that a missing bound is responsible, we don't show // this note as it is redundant. err.note(&format!( - "the trait `{}` is not implemented for `{}`", - missing_trait, lhs_ty + "the trait `{missing_trait}` is not implemented for `{lhs_ty}`" )); } } else { @@ -679,19 +678,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut visitor = TypeParamVisitor(vec![]); visitor.visit_ty(operand_ty); - if let [ty] = &visitor.0[..] { - if let ty::Param(p) = *operand_ty.kind() { - suggest_constraining_param( - self.tcx, - self.body_id, - &mut err, - *ty, - operand_ty, - missing_trait, - p, - true, - ); - } + if let [ty] = &visitor.0[..] && let ty::Param(p) = *operand_ty.kind() { + suggest_constraining_param( + self.tcx, + self.body_id, + &mut err, + *ty, + operand_ty, + missing_trait, + p, + true, + ); } let sp = self.tcx.sess.source_map().start_point(ex.span); @@ -722,10 +719,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion( ex.span, &format!( - "you may have meant the maximum value of `{}`", - actual + "you may have meant the maximum value of `{actual}`", ), - format!("{}::MAX", actual), + format!("{actual}::MAX"), Applicability::MaybeIncorrect, ); } @@ -988,7 +984,7 @@ fn suggest_constraining_param( set_output: bool, ) { let hir = tcx.hir(); - let msg = &format!("`{}` might need a bound for `{}`", lhs_ty, missing_trait); + let msg = &format!("`{lhs_ty}` might need a bound for `{missing_trait}`"); // Try to find the def-id and details for the parameter p. We have only the index, // so we have to find the enclosing function's def-id, then look through its declared // generic parameters to get the declaration. @@ -1002,13 +998,13 @@ fn suggest_constraining_param( .as_ref() .and_then(|node| node.generics()) { - let output = if set_output { format!("", rhs_ty) } else { String::new() }; + let output = if set_output { format!("") } else { String::new() }; suggest_constraining_type_param( tcx, generics, &mut err, - &format!("{}", lhs_ty), - &format!("{}{}", missing_trait, output), + &lhs_ty.to_string(), + &format!("{missing_trait}{output}"), None, ); } else { diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed new file mode 100644 index 00000000000..b69bad98888 --- /dev/null +++ b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed @@ -0,0 +1,21 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/82081 + +use std::collections::HashMap; + +struct Test { + v: u32, +} + +fn main() { + let mut map = HashMap::new(); + map.insert("a", Test { v: 0 }); + + for (_k, mut v) in map.iter_mut() { + //~^ HELP use mutable method + //~| NOTE this iterator yields `&` references + v.v += 1; + //~^ ERROR cannot assign to `v.v` + //~| NOTE `v` is a `&` reference + } +} diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs new file mode 100644 index 00000000000..9284410dfa3 --- /dev/null +++ b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs @@ -0,0 +1,21 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/82081 + +use std::collections::HashMap; + +struct Test { + v: u32, +} + +fn main() { + let mut map = HashMap::new(); + map.insert("a", Test { v: 0 }); + + for (_k, mut v) in map.iter() { + //~^ HELP use mutable method + //~| NOTE this iterator yields `&` references + v.v += 1; + //~^ ERROR cannot assign to `v.v` + //~| NOTE `v` is a `&` reference + } +} diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr new file mode 100644 index 00000000000..74433daa6ac --- /dev/null +++ b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr @@ -0,0 +1,15 @@ +error[E0594]: cannot assign to `v.v`, which is behind a `&` reference + --> $DIR/suggest-mut-method-for-loop-hashmap.rs:17:9 + | +LL | for (_k, mut v) in map.iter() { + | ---------- + | | | + | | help: use mutable method: `iter_mut()` + | this iterator yields `&` references +... +LL | v.v += 1; + | ^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index b594f9c441c..bc08b8eff3f 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit b594f9c441cf12319d10c14ba6a511d5c9db1b87 +Subproject commit bc08b8eff3f8e4da7c448d7b7f6461938c817a60