From 14daf47e0a3c9db7a347bfce510ad75174ccbbd8 Mon Sep 17 00:00:00 2001 From: Antonio Yang Date: Fri, 4 Mar 2022 00:22:15 +0800 Subject: [PATCH 1/8] Show ignore message in console and json output --- library/test/src/console.rs | 2 +- library/test/src/formatters/json.rs | 21 +++++++++++++++++++++ library/test/src/formatters/pretty.rs | 19 ++++++++++++++----- 3 files changed, 36 insertions(+), 6 deletions(-) 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..7b039164f48c7 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -121,6 +121,27 @@ impl OutputFormatter for JsonFormatter { ), TestResult::TrIgnored => { + #[cfg(not(bootstrap))] + if let Some(msg) = desc.ignore_message { + self.write_event( + "test", + desc.name.as_slice(), + "ignored", + exec_time, + stdout, + Some(&*format!(r#""message": "{}""#, EscapedString(msg))), + ) + } else { + self.write_event( + "test", + desc.name.as_slice(), + "ignored", + exec_time, + stdout, + None, + ) + } + #[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..f05c543498f5f 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, may_message: Option<&'static str>) -> io::Result<()> { + if let Some(message) = may_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<()> { @@ -59,10 +63,10 @@ impl PrettyFormatter { pub fn write_short_result( &mut self, - result: &str, + result: impl AsRef, color: term::color::Color, ) -> io::Result<()> { - self.write_pretty(result, color) + self.write_pretty(result.as_ref(), color) } pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> 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)))?; From 38b96b9a6459facd05097b0b2d9d82fb2da6d774 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 11 Mar 2022 07:30:21 -0500 Subject: [PATCH 2/8] Add tests for JSON and console output --- src/test/run-make-fulldeps/libtest-json/Makefile | 2 +- src/test/run-make-fulldeps/libtest-json/f.rs | 2 +- src/test/run-make-fulldeps/libtest-json/output-default.json | 2 +- .../libtest-json/output-stdout-success.json | 2 +- src/test/ui/test-attrs/test-type.rs | 5 ++--- src/test/ui/test-attrs/test-type.run.stdout | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) 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/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 From a063b3a4b6eed93d07c084d6e34dbe7d02e02b04 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 28 Mar 2022 11:47:01 -0700 Subject: [PATCH 3/8] diagnostics: do not suggest `map.iter_mut()()` --- .../rustc_borrowck/src/diagnostics/mutability_errors.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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, From 757ab6b55c1e06689d457550afe5da3955a22c3a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 28 Mar 2022 11:47:19 -0700 Subject: [PATCH 4/8] diagnostics: add regression test for #82081 --- .../suggest-mut-method-for-loop-hashmap.fixed | 21 +++++++++++++++++++ .../suggest-mut-method-for-loop-hashmap.rs | 21 +++++++++++++++++++ ...suggest-mut-method-for-loop-hashmap.stderr | 15 +++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed create mode 100644 src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs create mode 100644 src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr 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`. From f2506c911b9656c20a33a908fd14b5617b486096 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda <41065217+TaKO8Ki@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:15:09 +0900 Subject: [PATCH 5/8] use format-args-capture and remove an unnecessary nested block --- compiler/rustc_typeck/src/check/op.rs | 60 +++++++++++++-------------- 1 file changed, 28 insertions(+), 32 deletions(-) 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 { From acb9b7e842ab4c833051a920c2af34764eb4e7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 29 Mar 2022 08:31:05 +0300 Subject: [PATCH 6/8] :arrow_up: rust-analyzer --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 3a0ae49135711532ccda0dc35acafd3ea13a5422 Mon Sep 17 00:00:00 2001 From: Antonio Yang Date: Tue, 29 Mar 2022 19:41:16 +0800 Subject: [PATCH 7/8] Refactor after review Co-authored-by: Mara Bos --- library/test/src/formatters/json.rs | 30 ++++++++++----------------- library/test/src/formatters/pretty.rs | 6 +++--- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index 7b039164f48c7..737921c1e10dc 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -122,25 +122,17 @@ impl OutputFormatter for JsonFormatter { TestResult::TrIgnored => { #[cfg(not(bootstrap))] - if let Some(msg) = desc.ignore_message { - self.write_event( - "test", - desc.name.as_slice(), - "ignored", - exec_time, - stdout, - Some(&*format!(r#""message": "{}""#, EscapedString(msg))), - ) - } else { - self.write_event( - "test", - desc.name.as_slice(), - "ignored", - exec_time, - stdout, - None, - ) - } + 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 f05c543498f5f..023c0174c4f3f 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -45,8 +45,8 @@ impl PrettyFormatter { self.write_short_result("FAILED", term::color::RED) } - pub fn write_ignored(&mut self, may_message: Option<&'static str>) -> io::Result<()> { - if let Some(message) = may_message { + 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) @@ -63,7 +63,7 @@ impl PrettyFormatter { pub fn write_short_result( &mut self, - result: impl AsRef, + result: &str, color: term::color::Color, ) -> io::Result<()> { self.write_pretty(result.as_ref(), color) From b1c3494d88548222b7af7e8309a5446ea474319e Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 29 Mar 2022 15:53:09 +0200 Subject: [PATCH 8/8] Remove unnecessary .as_ref(). --- library/test/src/formatters/pretty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index 023c0174c4f3f..9b407df2190f3 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -66,7 +66,7 @@ impl PrettyFormatter { result: &str, color: term::color::Color, ) -> io::Result<()> { - self.write_pretty(result.as_ref(), color) + self.write_pretty(result, color) } pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {