From f8ee57be2c585c3fd8931eeb88994fbfcaa0f083 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 19 Jan 2022 13:43:27 -0600 Subject: [PATCH 01/14] `impl Display for io::ErrorKind` This avoids having to convert from `ErrorKind` to `Error` just to print the error message. --- library/std/src/io/error.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 210a9ec718315..074d693b83155 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -361,13 +361,29 @@ impl ErrorKind { } } +#[stable(feature = "io_errorkind_display", since = "1.60.0")] +impl fmt::Display for ErrorKind { + /// Shows a human-readable description of the `ErrorKind`. + /// + /// This is similar to `impl Display for Error`, but doesn't require first converting to Error. + /// + /// # Examples + /// ``` + /// use std::io::ErrorKind; + /// assert_eq!("entity not found", ErrorKind::NotFound.to_string()); + /// ``` + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.write_str(self.as_str()) + } +} + /// Intended for use for errors not exposed to the user, where allocating onto /// the heap (for normal construction via Error::new) is too costly. #[stable(feature = "io_error_from_errorkind", since = "1.14.0")] impl From for Error { /// Converts an [`ErrorKind`] into an [`Error`]. /// - /// This conversion allocates a new error with a simple representation of error kind. + /// This conversion creates a new error with a simple representation of error kind. /// /// # Examples /// From 7f2477810271d0e6e0e7025f0629a0213db90795 Mon Sep 17 00:00:00 2001 From: 5225225 <5225225@mailbox.org> Date: Mon, 17 Jan 2022 22:13:15 +0000 Subject: [PATCH 02/14] Suggest making base prefix lowercase if parsing fails --- compiler/rustc_parse/src/parser/expr.rs | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 693dd0051dad1..09b88e9e07b6a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1700,6 +1700,19 @@ impl<'a> Parser<'a> { s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) } + // Try to lowercase the prefix if it's a valid base prefix. + fn fix_base_capitalisation(s: &str) -> Option { + if let Some(stripped) = s.strip_prefix("B") { + Some(format!("0b{stripped}")) + } else if let Some(stripped) = s.strip_prefix("O") { + Some(format!("0o{stripped}")) + } else if let Some(stripped) = s.strip_prefix("X") { + Some(format!("0x{stripped}")) + } else { + None + } + } + let token::Lit { kind, suffix, .. } = lit; match err { // `NotLiteral` is not an error by itself, so we don't report @@ -1724,6 +1737,19 @@ impl<'a> Parser<'a> { self.struct_span_err(span, &msg) .help("valid widths are 8, 16, 32, 64 and 128") .emit(); + } else if let Some(fixed) = fix_base_capitalisation(suf) { + let msg = format!("invalid suffix `{}` for number literal", suf); + + self.struct_span_err(span, &msg) + .span_label(span, format!("invalid suffix `{}`", suf)) + .help("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase") + .span_suggestion( + span, + "try making the prefix lowercase", + fixed, + Applicability::MaybeIncorrect, + ) + .emit(); } else { let msg = format!("invalid suffix `{}` for number literal", suf); self.struct_span_err(span, &msg) From 9bf6a5de7705e83c110179580e996dcf74a5928f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 30 Jan 2022 17:37:11 -0500 Subject: [PATCH 03/14] Hide failed command unless in verbose mode This is particularly intended for invoking compiletest; the command line there is long (3,350 characters on my system) and takes up a lot of screen real estate for little benefit to the majority of those running bootstrap. This moves printing it to verbose mode (-v must be passed) which means that it's still possible to access when needed for debugging. The main downside is that CI logs will by-default become less usable for debugging (particularly) spurious failures, but it is pretty rare for us to really need the information there -- it's usually fairly obvious what is being run with a little investigation. --- src/bootstrap/lib.rs | 4 ++-- src/build_helper/lib.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 8569089f70128..e5f84d417bf0b 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -851,7 +851,7 @@ impl Build { return; } self.verbose(&format!("running: {:?}", cmd)); - run(cmd) + run(cmd, self.is_verbose()) } /// Runs a command, printing out nice contextual information if it fails. @@ -871,7 +871,7 @@ impl Build { return true; } self.verbose(&format!("running: {:?}", cmd)); - try_run(cmd) + try_run(cmd, self.is_verbose()) } /// Runs a command, printing out nice contextual information if it fails. diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 28e95d81bb7e4..24aded547315e 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -55,18 +55,18 @@ pub fn restore_library_path() { } } -pub fn run(cmd: &mut Command) { - if !try_run(cmd) { +pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) { + if !try_run(cmd, print_cmd_on_fail) { std::process::exit(1); } } -pub fn try_run(cmd: &mut Command) -> bool { +pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { let status = match cmd.status() { Ok(status) => status, Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), }; - if !status.success() { + if !status.success() && print_cmd_on_fail { println!( "\n\ncommand did not execute successfully: {:?}\n\ expected success, got: {}\n\n", From 1a77d6227cccdd66367fd1e9cd736c03ddda64ec Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Mon, 31 Jan 2022 17:39:38 +0900 Subject: [PATCH 04/14] kmc-solid: Increase the default stack size --- library/std/src/sys/itron/thread.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index ebcc9ab26e088..0d8a3ac716360 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -77,7 +77,8 @@ const LIFECYCLE_DETACHED_OR_JOINED: usize = usize::MAX; const LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE: usize = usize::MAX; // there's no single value for `JOINING` -pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * crate::mem::size_of::(); +// 64KiB for 32-bit ISAs, 128KiB for 64-bit ISAs. +pub const DEFAULT_MIN_STACK_SIZE: usize = 0x4000 * crate::mem::size_of::(); impl Thread { /// # Safety From 0b8f3729fb13e6262f1fa5055ec38d7033f95cd0 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 29 Jan 2022 14:36:35 +0100 Subject: [PATCH 05/14] Remove two unnecessary transmutes from opaque Encoder and Decoder --- compiler/rustc_serialize/src/opaque.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index c272c687a7e98..7a05d2b762a47 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -130,8 +130,7 @@ impl serialize::Encoder for Encoder { #[inline] fn emit_i8(&mut self, v: i8) -> EncodeResult { - let as_u8: u8 = unsafe { std::mem::transmute(v) }; - self.emit_u8(as_u8) + self.emit_u8(v as u8) } #[inline] @@ -629,9 +628,9 @@ impl<'a> serialize::Decoder for Decoder<'a> { #[inline] fn read_i8(&mut self) -> i8 { - let as_u8 = self.data[self.position]; + let value = self.data[self.position]; self.position += 1; - unsafe { ::std::mem::transmute(as_u8) } + value as i8 } #[inline] From ec3b711a4bcc8cb3af34b2cdf1ad110eef5981f9 Mon Sep 17 00:00:00 2001 From: 5225225 <5225225@mailbox.org> Date: Thu, 27 Jan 2022 22:22:33 +0000 Subject: [PATCH 06/14] Write UI tests, tweak message --- compiler/rustc_parse/src/parser/expr.rs | 5 +- .../ui/numeric/uppercase-base-prefix.fixed | 77 +++++++++++++++ src/test/ui/numeric/uppercase-base-prefix.rs | 77 +++++++++++++++ .../ui/numeric/uppercase-base-prefix.stderr | 98 +++++++++++++++++++ 4 files changed, 254 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/numeric/uppercase-base-prefix.fixed create mode 100644 src/test/ui/numeric/uppercase-base-prefix.rs create mode 100644 src/test/ui/numeric/uppercase-base-prefix.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 09b88e9e07b6a..0115d498a7fb8 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1738,11 +1738,10 @@ impl<'a> Parser<'a> { .help("valid widths are 8, 16, 32, 64 and 128") .emit(); } else if let Some(fixed) = fix_base_capitalisation(suf) { - let msg = format!("invalid suffix `{}` for number literal", suf); + let msg = "invalid base prefix for number literal"; self.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{}`", suf)) - .help("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase") + .note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase") .span_suggestion( span, "try making the prefix lowercase", diff --git a/src/test/ui/numeric/uppercase-base-prefix.fixed b/src/test/ui/numeric/uppercase-base-prefix.fixed new file mode 100644 index 0000000000000..1b1c837ec5040 --- /dev/null +++ b/src/test/ui/numeric/uppercase-base-prefix.fixed @@ -0,0 +1,77 @@ +// run-rustfix +// Checks that integers with an uppercase base prefix (0B, 0X, 0O) have a nice error +#![allow(unused_variables)] + +fn main() { + let a = 0xABCDEF; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABCDEF + + let b = 0o755; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o755 + + let c = 0b10101010; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b10101010 + + let d = 0xABC_DEF; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABC_DEF + + let e = 0o7_55; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o7_55 + + let f = 0b1010_1010; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b1010_1010 + + let g = 0xABC_DEF_u64; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABC_DEF_u64 + + let h = 0o7_55_u32; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o7_55_u32 + + let i = 0b1010_1010_u8; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b1010_1010_u8 + // + let j = 0xABCDEFu64; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABCDEFu64 + + let k = 0o755u32; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o755u32 + + let l = 0b10101010u8; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b10101010u8 +} diff --git a/src/test/ui/numeric/uppercase-base-prefix.rs b/src/test/ui/numeric/uppercase-base-prefix.rs new file mode 100644 index 0000000000000..233d553da6585 --- /dev/null +++ b/src/test/ui/numeric/uppercase-base-prefix.rs @@ -0,0 +1,77 @@ +// run-rustfix +// Checks that integers with an uppercase base prefix (0B, 0X, 0O) have a nice error +#![allow(unused_variables)] + +fn main() { + let a = 0XABCDEF; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABCDEF + + let b = 0O755; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o755 + + let c = 0B10101010; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b10101010 + + let d = 0XABC_DEF; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABC_DEF + + let e = 0O7_55; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o7_55 + + let f = 0B1010_1010; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b1010_1010 + + let g = 0XABC_DEF_u64; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABC_DEF_u64 + + let h = 0O7_55_u32; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o7_55_u32 + + let i = 0B1010_1010_u8; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b1010_1010_u8 + // + let j = 0XABCDEFu64; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABCDEFu64 + + let k = 0O755u32; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o755u32 + + let l = 0B10101010u8; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b10101010u8 +} diff --git a/src/test/ui/numeric/uppercase-base-prefix.stderr b/src/test/ui/numeric/uppercase-base-prefix.stderr new file mode 100644 index 0000000000000..4ba8d5224b3e6 --- /dev/null +++ b/src/test/ui/numeric/uppercase-base-prefix.stderr @@ -0,0 +1,98 @@ +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:6:13 + | +LL | let a = 0XABCDEF; + | ^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABCDEF` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:12:13 + | +LL | let b = 0O755; + | ^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o755` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:18:13 + | +LL | let c = 0B10101010; + | ^^^^^^^^^^ help: try making the prefix lowercase: `0b10101010` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:24:13 + | +LL | let d = 0XABC_DEF; + | ^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABC_DEF` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:30:13 + | +LL | let e = 0O7_55; + | ^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o7_55` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:36:13 + | +LL | let f = 0B1010_1010; + | ^^^^^^^^^^^ help: try making the prefix lowercase: `0b1010_1010` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:42:13 + | +LL | let g = 0XABC_DEF_u64; + | ^^^^^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABC_DEF_u64` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:48:13 + | +LL | let h = 0O7_55_u32; + | ^^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o7_55_u32` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:54:13 + | +LL | let i = 0B1010_1010_u8; + | ^^^^^^^^^^^^^^ help: try making the prefix lowercase: `0b1010_1010_u8` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:60:13 + | +LL | let j = 0XABCDEFu64; + | ^^^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABCDEFu64` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:66:13 + | +LL | let k = 0O755u32; + | ^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o755u32` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:72:13 + | +LL | let l = 0B10101010u8; + | ^^^^^^^^^^^^ help: try making the prefix lowercase: `0b10101010u8` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: aborting due to 12 previous errors + From c15ef58f4f67ee9ae02773642145650495f9f413 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Mon, 29 Nov 2021 01:50:12 +0100 Subject: [PATCH 07/14] Fix suggestion to slice if scrutinee is a `Result` or `Option` --- compiler/rustc_typeck/src/check/pat.rs | 38 +++++++++++++++++++++----- src/test/ui/typeck/issue-91328.fixed | 27 ++++++++++++++++++ src/test/ui/typeck/issue-91328.rs | 27 ++++++++++++++++++ src/test/ui/typeck/issue-91328.stderr | 21 ++++++++++++++ 4 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/typeck/issue-91328.fixed create mode 100644 src/test/ui/typeck/issue-91328.rs create mode 100644 src/test/ui/typeck/issue-91328.stderr diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 17b97d4cad1d4..9c2182a87ff1c 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -15,7 +15,7 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::hygiene::DesugaringKind; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::{Span, Spanned}; -use rustc_span::symbol::Ident; +use rustc_span::symbol::{sym, Ident}; use rustc_span::{BytePos, MultiSpan, DUMMY_SP}; use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::{ObligationCause, Pattern}; @@ -2033,12 +2033,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if let (Some(span), true) = (ti.span, ti.origin_expr) { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - err.span_suggestion( - span, - "consider slicing here", - format!("{}[..]", snippet), - Applicability::MachineApplicable, - ); + let applicability = match self.resolve_vars_if_possible(ti.expected).kind() { + ty::Adt(adt_def, _) + if self.tcx.is_diagnostic_item(sym::Option, adt_def.did) + || self.tcx.is_diagnostic_item(sym::Result, adt_def.did) => + { + // Slicing won't work here, but `.as_deref()` might (issue #91328). + err.span_suggestion( + span, + "consider using `as_deref` here", + format!("{}.as_deref()", snippet), + Applicability::MaybeIncorrect, + ); + None + } + ty::Adt(adt_def, _) + if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did) => + { + Some(Applicability::MachineApplicable) + } + _ => Some(Applicability::MaybeIncorrect), + }; + + if let Some(applicability) = applicability { + err.span_suggestion( + span, + "consider slicing here", + format!("{}[..]", snippet), + applicability, + ); + } } } } diff --git a/src/test/ui/typeck/issue-91328.fixed b/src/test/ui/typeck/issue-91328.fixed new file mode 100644 index 0000000000000..48dc26718da31 --- /dev/null +++ b/src/test/ui/typeck/issue-91328.fixed @@ -0,0 +1,27 @@ +// Regression test for issue #91328. + +// run-rustfix + +#![allow(dead_code)] + +fn foo(r: Result, i32>) -> i32 { + match r.as_deref() { + //~^ HELP: consider using `as_deref` here + Ok([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn bar(o: Option>) -> i32 { + match o.as_deref() { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-91328.rs b/src/test/ui/typeck/issue-91328.rs new file mode 100644 index 0000000000000..de5deb9534902 --- /dev/null +++ b/src/test/ui/typeck/issue-91328.rs @@ -0,0 +1,27 @@ +// Regression test for issue #91328. + +// run-rustfix + +#![allow(dead_code)] + +fn foo(r: Result, i32>) -> i32 { + match r { + //~^ HELP: consider using `as_deref` here + Ok([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn bar(o: Option>) -> i32 { + match o { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-91328.stderr b/src/test/ui/typeck/issue-91328.stderr new file mode 100644 index 0000000000000..4a9ddb2b92717 --- /dev/null +++ b/src/test/ui/typeck/issue-91328.stderr @@ -0,0 +1,21 @@ +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/issue-91328.rs:10:12 + | +LL | match r { + | - help: consider using `as_deref` here: `r.as_deref()` +LL | +LL | Ok([a, b]) => a + b, + | ^^^^^^ pattern cannot match with input type `Vec` + +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/issue-91328.rs:20:14 + | +LL | match o { + | - help: consider using `as_deref` here: `o.as_deref()` +LL | +LL | Some([a, b]) => a + b, + | ^^^^^^ pattern cannot match with input type `Vec` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0529`. From 0363f11ff03269d84eedb50d2130000fdfeceeb0 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Sat, 15 Jan 2022 21:33:11 +0100 Subject: [PATCH 08/14] Add match on `Vec<_>` to `ui/typeck/issue-91328.rs` test --- src/test/ui/typeck/issue-91328.fixed | 10 ++++++++++ src/test/ui/typeck/issue-91328.rs | 10 ++++++++++ src/test/ui/typeck/issue-91328.stderr | 11 ++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/test/ui/typeck/issue-91328.fixed b/src/test/ui/typeck/issue-91328.fixed index 48dc26718da31..81b6a99607215 100644 --- a/src/test/ui/typeck/issue-91328.fixed +++ b/src/test/ui/typeck/issue-91328.fixed @@ -24,4 +24,14 @@ fn bar(o: Option>) -> i32 { } } +fn baz(v: Vec) -> i32 { + match v[..] { + //~^ HELP: consider slicing here + [a, b] => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + fn main() {} diff --git a/src/test/ui/typeck/issue-91328.rs b/src/test/ui/typeck/issue-91328.rs index de5deb9534902..e938d8f5c9f04 100644 --- a/src/test/ui/typeck/issue-91328.rs +++ b/src/test/ui/typeck/issue-91328.rs @@ -24,4 +24,14 @@ fn bar(o: Option>) -> i32 { } } +fn baz(v: Vec) -> i32 { + match v { + //~^ HELP: consider slicing here + [a, b] => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + fn main() {} diff --git a/src/test/ui/typeck/issue-91328.stderr b/src/test/ui/typeck/issue-91328.stderr index 4a9ddb2b92717..96ad00cde4f7b 100644 --- a/src/test/ui/typeck/issue-91328.stderr +++ b/src/test/ui/typeck/issue-91328.stderr @@ -16,6 +16,15 @@ LL | LL | Some([a, b]) => a + b, | ^^^^^^ pattern cannot match with input type `Vec` -error: aborting due to 2 previous errors +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/issue-91328.rs:30:9 + | +LL | match v { + | - help: consider slicing here: `v[..]` +LL | +LL | [a, b] => a + b, + | ^^^^^^ pattern cannot match with input type `Vec` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0529`. From 67259e74a480c8bccc5a6f0c25c3b98c47be9f1d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 31 Jan 2022 10:56:40 -0800 Subject: [PATCH 09/14] Extract constant MARGIN out of Printer struct --- compiler/rustc_ast_pretty/src/pp.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs index e1f43cb20dc38..3e1b6e35170e2 100644 --- a/compiler/rustc_ast_pretty/src/pp.rs +++ b/compiler/rustc_ast_pretty/src/pp.rs @@ -199,10 +199,11 @@ enum PrintFrame { const SIZE_INFINITY: isize = 0xffff; +/// Target line width. +const MARGIN: isize = 78; + pub struct Printer { out: String, - /// Width of lines we're constrained to - margin: isize, /// Number of spaces left on line space: isize, /// Ring-buffer of tokens and calculated sizes @@ -237,11 +238,9 @@ struct BufEntry { impl Printer { pub fn new() -> Self { - let linewidth = 78; Printer { out: String::new(), - margin: linewidth as isize, - space: linewidth as isize, + space: MARGIN, buf: RingBuffer::new(), left_total: 0, right_total: 0, @@ -395,7 +394,7 @@ impl Printer { self.print_stack.push(PrintFrame::Broken { indent: self.indent, breaks: token.breaks }); self.indent = match token.indent { IndentStyle::Block { offset } => (self.indent as isize + offset) as usize, - IndentStyle::Visual => (self.margin - self.space) as usize, + IndentStyle::Visual => (MARGIN - self.space) as usize, }; } else { self.print_stack.push(PrintFrame::Fits); @@ -421,7 +420,7 @@ impl Printer { self.out.push('\n'); let indent = self.indent as isize + token.offset; self.pending_indentation = indent; - self.space = self.margin - indent; + self.space = MARGIN - indent; } } From 6db97b35d8b39c13fb145c930250a5682780e4a5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 31 Jan 2022 10:56:57 -0800 Subject: [PATCH 10/14] Allow any line to have at least 60 chars --- compiler/rustc_ast_pretty/src/pp.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs index 3e1b6e35170e2..26d600cefc7c0 100644 --- a/compiler/rustc_ast_pretty/src/pp.rs +++ b/compiler/rustc_ast_pretty/src/pp.rs @@ -136,6 +136,7 @@ mod ring; use ring::RingBuffer; use std::borrow::Cow; +use std::cmp; use std::collections::VecDeque; use std::iter; @@ -201,6 +202,8 @@ const SIZE_INFINITY: isize = 0xffff; /// Target line width. const MARGIN: isize = 78; +/// Every line is allowed at least this much space, even if highly indented. +const MIN_SPACE: isize = 60; pub struct Printer { out: String, @@ -420,7 +423,7 @@ impl Printer { self.out.push('\n'); let indent = self.indent as isize + token.offset; self.pending_indentation = indent; - self.space = MARGIN - indent; + self.space = cmp::max(MARGIN - indent, MIN_SPACE); } } From 7739fcab3062fdd71cf0d7377c86a5487e3638c1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 21 Jan 2022 02:28:11 -0800 Subject: [PATCH 11/14] Bless all pretty printer tests and ui tests --- src/test/pretty/issue-4264.pp | 3 +-- src/test/ui/match/issue-82392.stdout | 5 ++--- src/test/ui/proc-macro/quote-debug.stdout | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 3830c3aa6c9f1..ea74a267be81e 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -35,8 +35,7 @@ for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_v1 as fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test" - as &str)] as [&str; 1]) as - &[&str; 1]), + as &str)] as [&str; 1]) as &[&str; 1]), (&([] as [ArgumentV1; 0]) as &[ArgumentV1; 0])) as Arguments)) as String); (res as String) diff --git a/src/test/ui/match/issue-82392.stdout b/src/test/ui/match/issue-82392.stdout index 2054d43c40957..bcab76b7c6b69 100644 --- a/src/test/ui/match/issue-82392.stdout +++ b/src/test/ui/match/issue-82392.stdout @@ -11,7 +11,6 @@ pub fn main() ({ ({ } as ()) else if (let Some(a) = ((Some as - fn(i32) -> Option {Option::::Some})((3 - as i32)) as Option) as bool) ({ } as ()) - as ()) + fn(i32) -> Option {Option::::Some})((3 as i32)) as + Option) as bool) ({ } as ()) as ()) } as ()) diff --git a/src/test/ui/proc-macro/quote-debug.stdout b/src/test/ui/proc-macro/quote-debug.stdout index 79651f01b9534..a648d6b6d4b54 100644 --- a/src/test/ui/proc-macro/quote-debug.stdout +++ b/src/test/ui/proc-macro/quote-debug.stdout @@ -27,8 +27,7 @@ fn main() { crate::TokenStream::from(crate::TokenTree::Literal({ let mut iter = "\"world\"".parse::().unwrap().into_iter(); - if let (Some(crate::TokenTree::Literal(mut lit)), - None) = + if let (Some(crate::TokenTree::Literal(mut lit)), None) = (iter.next(), iter.next()) { lit.set_span(crate::Span::recover_proc_macro_span(2)); lit From 95344c02fd72511d3c87eb36f2fb36e28562934a Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Mon, 31 Jan 2022 20:34:26 +0100 Subject: [PATCH 12/14] Add FIXME comment --- compiler/rustc_typeck/src/check/pat.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 9c2182a87ff1c..62cd9c64a4a7c 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -2047,6 +2047,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); None } + // FIXME: instead of checking for Vec only, we could check whether the + // type implements `Deref`; see + // https://github.com/rust-lang/rust/pull/91343#discussion_r761466979 ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did) => { From 641bde0142b622cbfbcab642de3fabb7d01ffc38 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 1 Feb 2022 02:55:55 -0800 Subject: [PATCH 13/14] Update books --- src/doc/book | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rustc-dev-guide | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/book b/src/doc/book index f17df27fc1469..98904efaa4fc9 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit f17df27fc14696912c48b8b7a7a8fa49e648088d +Subproject commit 98904efaa4fc968db8ff59cf2744d9f7ed158166 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 8c395bdd8073d..d5fc1bce3f8eb 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 8c395bdd8073deb20ca67e1ed4b14a3a7e315a37 +Subproject commit d5fc1bce3f8eb398f9c25f1b15e0257d7537cd41 diff --git a/src/doc/nomicon b/src/doc/nomicon index 66d097d3d80e8..9493715a6280a 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 66d097d3d80e8f88c288c6879c7c2b909ecf8ad4 +Subproject commit 9493715a6280a1f74be759c7e1ef9999b5d13e6f diff --git a/src/doc/reference b/src/doc/reference index 4dee6eb63d728..411c2f0d5cebf 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 4dee6eb63d728ffb9e7a2ed443e9ada9275c69d2 +Subproject commit 411c2f0d5cebf48453ae2d136ad0c5e611d39aec diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 78dd6a4684cf8..8763adb62c712 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 78dd6a4684cf8d6b72275fab6d0429ea40b66338 +Subproject commit 8763adb62c712df69b1d39ea3e692b6d696cc4d9 From 91aee65c99c1077d7b39561746d2364e6d6d3d60 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 1 Feb 2022 03:26:30 -0800 Subject: [PATCH 14/14] Update cargo --- Cargo.lock | 10 +++++----- src/tools/cargo | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dd45d49781a45..1e124963d0d37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,7 +337,7 @@ dependencies = [ "cargo-test-macro", "cargo-test-support", "cargo-util", - "clap 3.0.10", + "clap 3.0.13", "crates-io", "crossbeam-utils", "curl", @@ -627,9 +627,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.10" +version = "3.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a30c3bf9ff12dfe5dae53f0a96e0febcd18420d1c0e7fad77796d9d5c4b5375" +checksum = "08799f92c961c7a1cf0cc398a9073da99e21ce388b46372c37f3191f2f3eed3e" dependencies = [ "atty", "bitflags", @@ -5233,9 +5233,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.13.0" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b80ac5e1b91e3378c63dab121962472b5ca20cf9ab1975e3d588548717807a8" +checksum = "744e9ed5b352340aa47ce033716991b5589e23781acb97cad37d4ea70560f55b" dependencies = [ "combine", "indexmap", diff --git a/src/tools/cargo b/src/tools/cargo index 1c034752de0df..25fcb135d02ea 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 1c034752de0df744fcd7788fcbca158830b8bf85 +Subproject commit 25fcb135d02ea897ce894b67ae021f48107d522b