diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index c77bbeb86e586..6e551e95cbb43 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 e0dbe027aefe9..9b37985ce4932 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/library/test/src/console.rs b/library/test/src/console.rs index c7e8507113e0c..56eef8314fbde 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -118,7 +118,7 @@ impl ConsoleTestState { TestResult::TrIgnored => { #[cfg(not(bootstrap))] if let Some(msg) = ignore_message { - format!("ignored, {msg}") + format!("ignored: {msg}") } else { "ignored".to_owned() } diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index c089bfc4791b5..737921c1e10dc 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -121,6 +121,19 @@ impl OutputFormatter for JsonFormatter { ), TestResult::TrIgnored => { + #[cfg(not(bootstrap))] + return self.write_event( + "test", + desc.name.as_slice(), + "ignored", + exec_time, + stdout, + desc.ignore_message + .map(|msg| format!(r#""message": "{}""#, EscapedString(msg))) + .as_deref(), + ); + + #[cfg(bootstrap)] self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None) } diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index f55d390aa5621..9b407df2190f3 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -45,8 +45,12 @@ impl PrettyFormatter { self.write_short_result("FAILED", term::color::RED) } - pub fn write_ignored(&mut self) -> io::Result<()> { - self.write_short_result("ignored", term::color::YELLOW) + pub fn write_ignored(&mut self, message: Option<&'static str>) -> io::Result<()> { + if let Some(message) = message { + self.write_short_result(&format!("ignored, {}", message), term::color::YELLOW) + } else { + self.write_short_result("ignored", term::color::YELLOW) + } } pub fn write_time_failed(&mut self) -> io::Result<()> { @@ -214,7 +218,12 @@ impl OutputFormatter for PrettyFormatter { match *result { TestResult::TrOk => self.write_ok()?, TestResult::TrFailed | TestResult::TrFailedMsg(_) => self.write_failed()?, - TestResult::TrIgnored => self.write_ignored()?, + TestResult::TrIgnored => { + #[cfg(not(bootstrap))] + self.write_ignored(desc.ignore_message)?; + #[cfg(bootstrap)] + self.write_ignored(None)?; + } TestResult::TrBench(ref bs) => { self.write_bench()?; self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?; diff --git a/src/test/run-make-fulldeps/libtest-json/Makefile b/src/test/run-make-fulldeps/libtest-json/Makefile index f61a1aa84100f..67b5fc2ed32dc 100644 --- a/src/test/run-make-fulldeps/libtest-json/Makefile +++ b/src/test/run-make-fulldeps/libtest-json/Makefile @@ -5,7 +5,7 @@ OUTPUT_FILE_DEFAULT := $(TMPDIR)/libtest-json-output-default.json OUTPUT_FILE_STDOUT_SUCCESS := $(TMPDIR)/libtest-json-output-stdout-success.json -all: +all: f.rs validate_json.py output-default.json output-stdout-success.json $(RUSTC) --test f.rs RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE_DEFAULT) || true RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json --show-output > $(OUTPUT_FILE_STDOUT_SUCCESS) || true diff --git a/src/test/run-make-fulldeps/libtest-json/f.rs b/src/test/run-make-fulldeps/libtest-json/f.rs index 95ff36bd764ec..edfe25086ae9a 100644 --- a/src/test/run-make-fulldeps/libtest-json/f.rs +++ b/src/test/run-make-fulldeps/libtest-json/f.rs @@ -16,7 +16,7 @@ fn c() { } #[test] -#[ignore] +#[ignore = "msg"] fn d() { assert!(false); } diff --git a/src/test/run-make-fulldeps/libtest-json/output-default.json b/src/test/run-make-fulldeps/libtest-json/output-default.json index e2c778aa86509..63342abc6ef71 100644 --- a/src/test/run-make-fulldeps/libtest-json/output-default.json +++ b/src/test/run-make-fulldeps/libtest-json/output-default.json @@ -6,5 +6,5 @@ { "type": "test", "event": "started", "name": "c" } { "type": "test", "name": "c", "event": "ok" } { "type": "test", "event": "started", "name": "d" } -{ "type": "test", "name": "d", "event": "ignored" } +{ "type": "test", "name": "d", "event": "ignored", "message": "msg" } { "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME } diff --git a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json index 68eb00c297ea7..8f19114460e89 100644 --- a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json +++ b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json @@ -6,5 +6,5 @@ { "type": "test", "event": "started", "name": "c" } { "type": "test", "name": "c", "event": "ok", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:15:5\n" } { "type": "test", "event": "started", "name": "d" } -{ "type": "test", "name": "d", "event": "ignored" } +{ "type": "test", "name": "d", "event": "ignored", "message": "msg" } { "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME } 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 0000000000000..b69bad98888e3 --- /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 0000000000000..9284410dfa383 --- /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 0000000000000..74433daa6acf2 --- /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/test/ui/test-attrs/test-type.rs b/src/test/ui/test-attrs/test-type.rs index 3f0fa81373f10..f99e476eabae3 100644 --- a/src/test/ui/test-attrs/test-type.rs +++ b/src/test/ui/test-attrs/test-type.rs @@ -5,7 +5,6 @@ // ignore-emscripten no threads support // run-pass - #[test] fn test_ok() { let _a = true; @@ -18,9 +17,9 @@ fn test_panic() { } #[test] -#[ignore] +#[ignore = "msg"] fn test_no_run() { - loop{ + loop { println!("Hello, world"); } } diff --git a/src/test/ui/test-attrs/test-type.run.stdout b/src/test/ui/test-attrs/test-type.run.stdout index be2fd8ae68c36..143c13a36b7e7 100644 --- a/src/test/ui/test-attrs/test-type.run.stdout +++ b/src/test/ui/test-attrs/test-type.run.stdout @@ -1,6 +1,6 @@ running 3 tests -test test_no_run ... ignored +test test_no_run ... ignored, msg test test_ok ... ok test test_panic - should panic ... ok diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index b594f9c441cf1..bc08b8eff3f8e 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit b594f9c441cf12319d10c14ba6a511d5c9db1b87 +Subproject commit bc08b8eff3f8e4da7c448d7b7f6461938c817a60