From 2a270a0066c6cf1d713eedc1e096548cee5442fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anselm=20Sch=C3=BCler?= Date: Sun, 27 Aug 2023 19:16:15 +0200 Subject: [PATCH 1/9] Remove parens around .. in documentation snippet --- library/core/src/ops/range.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index ba5e6ddc752a4..cc596293ca3fe 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -11,7 +11,7 @@ use crate::hash::Hash; /// The `..` syntax is a `RangeFull`: /// /// ``` -/// assert_eq!((..), std::ops::RangeFull); +/// assert_eq!(.., std::ops::RangeFull); /// ``` /// /// It does not have an [`IntoIterator`] implementation, so you can't use it in From a293619caad49bb0e8d9a4d417bedf50f31d1b06 Mon Sep 17 00:00:00 2001 From: Sebastian Toh Date: Sun, 27 Aug 2023 20:14:56 +0800 Subject: [PATCH 2/9] Add note that str cannot be matched exhaustively --- .../src/thir/pattern/check_match.rs | 16 ++++++++++------ .../issue-105479-str-non-exhaustiveness.rs | 12 ++++++++++++ .../issue-105479-str-non-exhaustiveness.stderr | 17 +++++++++++++++++ tests/ui/pattern/usefulness/issue-30240.stderr | 2 ++ 4 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.rs create mode 100644 tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index f46cf0dc0ff1b..cce2a8c5259a4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -735,17 +735,21 @@ fn non_exhaustive_match<'p, 'tcx>( collect_non_exhaustive_tys(&witnesses[0], &mut non_exhaustive_tys); for ty in non_exhaustive_tys { - if ty == cx.tcx.types.usize || ty == cx.tcx.types.isize { + if ty.is_ptr_sized_integral() { err.note(format!( "`{ty}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \ - exhaustively", - )); + exhaustively", + )); if cx.tcx.sess.is_nightly_build() { err.help(format!( - "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \ - enable precise `{ty}` matching", - )); + "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \ + enable precise `{ty}` matching", + )); } + } else if ty == cx.tcx.types.str_ { + err.note(format!( + "`{ty}` cannot be matched exhaustively, so a wildcard `_` is necessary", + )); } } } diff --git a/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.rs b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.rs new file mode 100644 index 0000000000000..faf37b07513f6 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.rs @@ -0,0 +1,12 @@ +fn main() { + let a = ""; + let b = ""; + match (a, b) { + //~^ ERROR non-exhaustive patterns: `(&_, _)` not covered [E0004] + //~| NOTE pattern `(&_, _)` not covered + //~| NOTE the matched value is of type `(&str, &str)` + //~| NOTE `str` cannot be matched exhaustively, so a wildcard `_` is necessary + ("a", "b") => {} + ("c", "d") => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr new file mode 100644 index 0000000000000..5c09b3bada6b9 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: `(&_, _)` not covered + --> $DIR/issue-105479-str-non-exhaustiveness.rs:4:11 + | +LL | match (a, b) { + | ^^^^^^ pattern `(&_, _)` not covered + | + = note: the matched value is of type `(&str, &str)` + = note: `str` cannot be matched exhaustively, so a wildcard `_` is necessary +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ ("c", "d") => {}, +LL + (&_, _) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-30240.stderr b/tests/ui/pattern/usefulness/issue-30240.stderr index ff755d681ac73..736ab34e16468 100644 --- a/tests/ui/pattern/usefulness/issue-30240.stderr +++ b/tests/ui/pattern/usefulness/issue-30240.stderr @@ -5,6 +5,7 @@ LL | match "world" { | ^^^^^^^ pattern `&_` not covered | = note: the matched value is of type `&str` + = note: `str` cannot be matched exhaustively, so a wildcard `_` is necessary help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ "hello" => {}, @@ -18,6 +19,7 @@ LL | match "world" { | ^^^^^^^ pattern `&_` not covered | = note: the matched value is of type `&str` + = note: `str` cannot be matched exhaustively, so a wildcard `_` is necessary help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ "hello" => {}, From 43dd8613a308745a9f75690bb5365f8b8ca05926 Mon Sep 17 00:00:00 2001 From: Sebastian Toh Date: Mon, 28 Aug 2023 14:25:52 +0800 Subject: [PATCH 3/9] Add note when matching on nested non-exhaustive enums --- .../src/thir/pattern/check_match.rs | 11 ++--- .../src/thir/pattern/usefulness.rs | 49 ++++++++++--------- .../match/non-exhaustive-match.stderr | 3 +- tests/ui/match/match_non_exhaustive.stderr | 3 +- .../usefulness/auxiliary/non-exhaustive.rs | 2 + .../usefulness/nested-non-exhaustive-enums.rs | 18 +++++++ .../nested-non-exhaustive-enums.stderr | 22 +++++++++ .../rfcs/rfc-2008-non-exhaustive/enum.stderr | 5 +- 8 files changed, 78 insertions(+), 35 deletions(-) create mode 100644 tests/ui/pattern/usefulness/auxiliary/non-exhaustive.rs create mode 100644 tests/ui/pattern/usefulness/nested-non-exhaustive-enums.rs create mode 100644 tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index cce2a8c5259a4..38c24e0ab5ee3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -720,15 +720,8 @@ fn non_exhaustive_match<'p, 'tcx>( }; }; - let is_variant_list_non_exhaustive = matches!(scrut_ty.kind(), - ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local()); - adt_defined_here(cx, &mut err, scrut_ty, &witnesses); - err.note(format!( - "the matched value is of type `{}`{}", - scrut_ty, - if is_variant_list_non_exhaustive { ", which is marked as non-exhaustive" } else { "" } - )); + err.note(format!("the matched value is of type `{}`", scrut_ty)); if !is_empty_match && witnesses.len() == 1 { let mut non_exhaustive_tys = FxHashSet::default(); @@ -750,6 +743,8 @@ fn non_exhaustive_match<'p, 'tcx>( err.note(format!( "`{ty}` cannot be matched exhaustively, so a wildcard `_` is necessary", )); + } else if cx.is_foreign_non_exhaustive_enum(ty) { + err.note(format!("`{ty}` is marked as non-exhaustive")); } } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 08cfe98bb68b9..21031e8ba9d7e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -618,10 +618,15 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> { let new_witnesses = if let Constructor::Missing { .. } = ctor { // We got the special `Missing` constructor, so each of the missing constructors // gives a new pattern that is not caught by the match. We list those patterns. - let new_patterns = if pcx.is_non_exhaustive { - // Here we don't want the user to try to list all variants, we want them to add - // a wildcard, so we only suggest that. - vec![DeconstructedPat::wildcard(pcx.ty, pcx.span)] + if pcx.is_non_exhaustive { + witnesses + .into_iter() + // Here we don't want the user to try to list all variants, we want them to add + // a wildcard, so we only suggest that. + .map(|witness| { + witness.apply_constructor(pcx, &Constructor::NonExhaustive) + }) + .collect() } else { let mut split_wildcard = SplitWildcard::new(pcx); split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor)); @@ -633,7 +638,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> { // constructor, that matches everything that can be built with // it. For example, if `ctor` is a `Constructor::Variant` for // `Option::Some`, we get the pattern `Some(_)`. - let mut new: Vec> = split_wildcard + let mut new_patterns: Vec> = split_wildcard .iter_missing(pcx) .filter_map(|missing_ctor| { // Check if this variant is marked `doc(hidden)` @@ -648,27 +653,25 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> { .collect(); if hide_variant_show_wild { - new.push(DeconstructedPat::wildcard(pcx.ty, pcx.span)); + new_patterns.push(DeconstructedPat::wildcard(pcx.ty, pcx.span)); } - new - }; - - witnesses - .into_iter() - .flat_map(|witness| { - new_patterns.iter().map(move |pat| { - Witness( - witness - .0 - .iter() - .chain(once(pat)) - .map(DeconstructedPat::clone_and_forget_reachability) - .collect(), - ) + witnesses + .into_iter() + .flat_map(|witness| { + new_patterns.iter().map(move |pat| { + Witness( + witness + .0 + .iter() + .chain(once(pat)) + .map(DeconstructedPat::clone_and_forget_reachability) + .collect(), + ) + }) }) - }) - .collect() + .collect() + } } else { witnesses .into_iter() diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr index 3a5fad15421c6..fddd769c3dfc3 100644 --- a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr @@ -45,7 +45,8 @@ note: `E2` defined here | LL | pub enum E2 { A, B } | ^^^^^^^^^^^ - = note: the matched value is of type `E2`, which is marked as non-exhaustive + = note: the matched value is of type `E2` + = note: `E2` is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | let _e = || { match e2 { E2::A => (), E2::B => (), _ => todo!() } }; diff --git a/tests/ui/match/match_non_exhaustive.stderr b/tests/ui/match/match_non_exhaustive.stderr index 46ee8d5179e6b..d07e284e299bb 100644 --- a/tests/ui/match/match_non_exhaustive.stderr +++ b/tests/ui/match/match_non_exhaustive.stderr @@ -45,7 +45,8 @@ note: `E2` defined here | LL | pub enum E2 { A, B } | ^^^^^^^^^^^ - = note: the matched value is of type `E2`, which is marked as non-exhaustive + = note: the matched value is of type `E2` + = note: `E2` is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match e2 { E2::A => (), E2::B => (), _ => todo!() }; diff --git a/tests/ui/pattern/usefulness/auxiliary/non-exhaustive.rs b/tests/ui/pattern/usefulness/auxiliary/non-exhaustive.rs new file mode 100644 index 0000000000000..6f459b8268f6f --- /dev/null +++ b/tests/ui/pattern/usefulness/auxiliary/non-exhaustive.rs @@ -0,0 +1,2 @@ +#[non_exhaustive] +pub enum NonExhaustiveEnum { A, B } diff --git a/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.rs b/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.rs new file mode 100644 index 0000000000000..3a8a74d1fd65f --- /dev/null +++ b/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.rs @@ -0,0 +1,18 @@ +// aux-build:non-exhaustive.rs + +extern crate non_exhaustive; + +use non_exhaustive::NonExhaustiveEnum; + +fn main() { + match Some(NonExhaustiveEnum::A) { + //~^ ERROR non-exhaustive patterns: `Some(_)` not covered [E0004] + //~| NOTE pattern `Some(_)` not covered + //~| NOTE `Option` defined here + //~| NOTE the matched value is of type `Option` + //~| NOTE `NonExhaustiveEnum` is marked as non-exhaustive + Some(NonExhaustiveEnum::A) => {} + Some(NonExhaustiveEnum::B) => {} + None => {} + } +} diff --git a/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr b/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr new file mode 100644 index 0000000000000..ae81f307fde34 --- /dev/null +++ b/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr @@ -0,0 +1,22 @@ +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/nested-non-exhaustive-enums.rs:8:11 + | +LL | match Some(NonExhaustiveEnum::A) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` + = note: `NonExhaustiveEnum` is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr index 872cb9b8bc68e..50209e18bd173 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr @@ -28,7 +28,8 @@ note: `NonExhaustiveEnum` defined here | LL | pub enum NonExhaustiveEnum { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive + = note: the matched value is of type `NonExhaustiveEnum` + = note: `NonExhaustiveEnum` is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ NonExhaustiveEnum::Struct { .. } => "third", @@ -46,7 +47,7 @@ note: `NonExhaustiveEnum` defined here | LL | pub enum NonExhaustiveEnum { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive + = note: the matched value is of type `NonExhaustiveEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ match enum_unit { From 4429ccfa9ff6f0d540ea5ccfb51b548d71c46125 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Mon, 28 Aug 2023 11:57:32 -0400 Subject: [PATCH 4/9] Reference uplifted clippy lints' rustc name in the release notes I updated to Rust 1.72.0, got a new warning from rustc, wanted to read more about it, so I went to RELEASES.md and searched for the new lint's name as shown in the warning I got. I found no results because the relevant entry in RELEASES only contained the lint's old Clippy name, not its new rustc name. This adds the rustc name for lints so that someone doing the same thing I did will have more success. Some of the uplifted lints didn't have a name change, so I didn't add the rustc name as a search for it will succeed. --- RELEASES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 242b1c2eefd28..5431df06d50d7 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -10,9 +10,9 @@ Language - [expand: Change how `#![cfg(FALSE)]` behaves on crate root](https://github.com/rust-lang/rust/pull/110141/) - [Stabilize inline asm for LoongArch64](https://github.com/rust-lang/rust/pull/111235/) - [Uplift `clippy::undropped_manually_drops` lint](https://github.com/rust-lang/rust/pull/111530/) -- [Uplift `clippy::invalid_utf8_in_unchecked` lint](https://github.com/rust-lang/rust/pull/111543/) +- [Uplift `clippy::invalid_utf8_in_unchecked` lint](https://github.com/rust-lang/rust/pull/111543/) as `invalid_from_utf8_unchecked` and `invalid_from_utf8` - [Uplift `clippy::cast_ref_to_mut` lint](https://github.com/rust-lang/rust/pull/111567/) -- [Uplift `clippy::cmp_nan` lint](https://github.com/rust-lang/rust/pull/111818/) +- [Uplift `clippy::cmp_nan` lint](https://github.com/rust-lang/rust/pull/111818/) as `invalid_nan_comparisons` - [resolve: Remove artificial import ambiguity errors](https://github.com/rust-lang/rust/pull/112086/) - [Don't require associated types with Self: Sized bounds in `dyn Trait` objects](https://github.com/rust-lang/rust/pull/112319/) From 695068903034e326fa2d58bee8314bef903ce54f Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 1 Sep 2023 19:12:37 +0300 Subject: [PATCH 5/9] remove some unused crate deps --- Cargo.lock | 4 ---- compiler/rustc_query_impl/Cargo.toml | 1 - compiler/rustc_traits/Cargo.toml | 3 --- 3 files changed, 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84a668b5188ce..bdbafb8623bb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4228,7 +4228,6 @@ dependencies = [ "measureme", "memoffset", "rustc-rayon-core", - "rustc_ast", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4437,15 +4436,12 @@ dependencies = [ name = "rustc_traits" version = "0.0.0" dependencies = [ - "rustc_ast", "rustc_data_structures", "rustc_hir", "rustc_infer", "rustc_middle", "rustc_span", - "rustc_target", "rustc_trait_selection", - "smallvec", "tracing", ] diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index ac697a3ae3e99..a44dd5ede2fd2 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -9,7 +9,6 @@ edition = "2021" [dependencies] field-offset = "0.3.5" measureme = "10.0.0" -rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index 37e00c0e4bcff..0cdc978a3d022 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -8,9 +8,6 @@ tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } -rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -rustc_target = { path = "../rustc_target" } -smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } rustc_infer = { path = "../rustc_infer" } rustc_trait_selection = { path = "../rustc_trait_selection" } From d9af418223e26df77923a2fbe82a6c2c7d5fa5a7 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Sat, 2 Sep 2023 20:45:52 -0400 Subject: [PATCH 6/9] Add another renamed Clippy lint to release notes --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 5431df06d50d7..c5ac070b317b3 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -11,7 +11,7 @@ Language - [Stabilize inline asm for LoongArch64](https://github.com/rust-lang/rust/pull/111235/) - [Uplift `clippy::undropped_manually_drops` lint](https://github.com/rust-lang/rust/pull/111530/) - [Uplift `clippy::invalid_utf8_in_unchecked` lint](https://github.com/rust-lang/rust/pull/111543/) as `invalid_from_utf8_unchecked` and `invalid_from_utf8` -- [Uplift `clippy::cast_ref_to_mut` lint](https://github.com/rust-lang/rust/pull/111567/) +- [Uplift `clippy::cast_ref_to_mut` lint](https://github.com/rust-lang/rust/pull/111567/) as `invalid_reference_casting` - [Uplift `clippy::cmp_nan` lint](https://github.com/rust-lang/rust/pull/111818/) as `invalid_nan_comparisons` - [resolve: Remove artificial import ambiguity errors](https://github.com/rust-lang/rust/pull/112086/) - [Don't require associated types with Self: Sized bounds in `dyn Trait` objects](https://github.com/rust-lang/rust/pull/112319/) From d87b87d10e630eb0fb9cd0bf11c70ee869f077b7 Mon Sep 17 00:00:00 2001 From: Sebastian Toh Date: Sun, 3 Sep 2023 19:55:11 +0800 Subject: [PATCH 7/9] Improve clarity of diagnostic message on non-exhaustive matches --- compiler/rustc_mir_build/src/thir/pattern/check_match.rs | 4 ++-- .../2229_closure_analysis/match/non-exhaustive-match.stderr | 2 +- tests/ui/match/match_non_exhaustive.stderr | 2 +- .../pattern/usefulness/issue-105479-str-non-exhaustiveness.rs | 2 +- .../usefulness/issue-105479-str-non-exhaustiveness.stderr | 2 +- tests/ui/pattern/usefulness/issue-30240.stderr | 4 ++-- .../ui/pattern/usefulness/nested-non-exhaustive-enums.stderr | 2 +- tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 38c24e0ab5ee3..95dced644e161 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -741,10 +741,10 @@ fn non_exhaustive_match<'p, 'tcx>( } } else if ty == cx.tcx.types.str_ { err.note(format!( - "`{ty}` cannot be matched exhaustively, so a wildcard `_` is necessary", + "`&str` cannot be matched exhaustively, so a wildcard `_` is necessary", )); } else if cx.is_foreign_non_exhaustive_enum(ty) { - err.note(format!("`{ty}` is marked as non-exhaustive")); + err.note(format!("`{ty}` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively")); } } } diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr index fddd769c3dfc3..0807f4590298f 100644 --- a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr @@ -46,7 +46,7 @@ note: `E2` defined here LL | pub enum E2 { A, B } | ^^^^^^^^^^^ = note: the matched value is of type `E2` - = note: `E2` is marked as non-exhaustive + = note: `E2` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | let _e = || { match e2 { E2::A => (), E2::B => (), _ => todo!() } }; diff --git a/tests/ui/match/match_non_exhaustive.stderr b/tests/ui/match/match_non_exhaustive.stderr index d07e284e299bb..7b8bdfe0053ae 100644 --- a/tests/ui/match/match_non_exhaustive.stderr +++ b/tests/ui/match/match_non_exhaustive.stderr @@ -46,7 +46,7 @@ note: `E2` defined here LL | pub enum E2 { A, B } | ^^^^^^^^^^^ = note: the matched value is of type `E2` - = note: `E2` is marked as non-exhaustive + = note: `E2` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match e2 { E2::A => (), E2::B => (), _ => todo!() }; diff --git a/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.rs b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.rs index faf37b07513f6..0ee7856c6803a 100644 --- a/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.rs +++ b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.rs @@ -5,7 +5,7 @@ fn main() { //~^ ERROR non-exhaustive patterns: `(&_, _)` not covered [E0004] //~| NOTE pattern `(&_, _)` not covered //~| NOTE the matched value is of type `(&str, &str)` - //~| NOTE `str` cannot be matched exhaustively, so a wildcard `_` is necessary + //~| NOTE `&str` cannot be matched exhaustively, so a wildcard `_` is necessary ("a", "b") => {} ("c", "d") => {} } diff --git a/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr index 5c09b3bada6b9..771fc320a13f6 100644 --- a/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr +++ b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr @@ -5,7 +5,7 @@ LL | match (a, b) { | ^^^^^^ pattern `(&_, _)` not covered | = note: the matched value is of type `(&str, &str)` - = note: `str` cannot be matched exhaustively, so a wildcard `_` is necessary + = note: `&str` cannot be matched exhaustively, so a wildcard `_` is necessary help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ ("c", "d") => {}, diff --git a/tests/ui/pattern/usefulness/issue-30240.stderr b/tests/ui/pattern/usefulness/issue-30240.stderr index 736ab34e16468..da8bbdffbf6d5 100644 --- a/tests/ui/pattern/usefulness/issue-30240.stderr +++ b/tests/ui/pattern/usefulness/issue-30240.stderr @@ -5,7 +5,7 @@ LL | match "world" { | ^^^^^^^ pattern `&_` not covered | = note: the matched value is of type `&str` - = note: `str` cannot be matched exhaustively, so a wildcard `_` is necessary + = note: `&str` cannot be matched exhaustively, so a wildcard `_` is necessary help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ "hello" => {}, @@ -19,7 +19,7 @@ LL | match "world" { | ^^^^^^^ pattern `&_` not covered | = note: the matched value is of type `&str` - = note: `str` cannot be matched exhaustively, so a wildcard `_` is necessary + = note: `&str` cannot be matched exhaustively, so a wildcard `_` is necessary help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ "hello" => {}, diff --git a/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr b/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr index ae81f307fde34..9fbd871db7c9d 100644 --- a/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr +++ b/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr @@ -10,7 +10,7 @@ note: `Option` defined here | = note: not covered = note: the matched value is of type `Option` - = note: `NonExhaustiveEnum` is marked as non-exhaustive + = note: `NonExhaustiveEnum` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => {}, diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr index 50209e18bd173..4e7f3098ab482 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum.stderr @@ -29,7 +29,7 @@ note: `NonExhaustiveEnum` defined here LL | pub enum NonExhaustiveEnum { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `NonExhaustiveEnum` - = note: `NonExhaustiveEnum` is marked as non-exhaustive + = note: `NonExhaustiveEnum` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ NonExhaustiveEnum::Struct { .. } => "third", From 372f91be7758390b66abc0430787dc56ab0b5e36 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 19 May 2023 16:03:35 -0400 Subject: [PATCH 8/9] Print a backtrace in const eval if interrupted --- Cargo.lock | 12 ++++++------ compiler/rustc_const_eval/messages.ftl | 2 ++ .../src/const_eval/eval_queries.rs | 8 +++++++- compiler/rustc_const_eval/src/errors.rs | 1 + compiler/rustc_data_structures/src/lib.rs | 7 +++++++ compiler/rustc_driver_impl/Cargo.toml | 1 + compiler/rustc_driver_impl/src/lib.rs | 14 ++++++++++++++ compiler/rustc_middle/src/mir/interpret/error.rs | 2 ++ src/tools/miri/src/concurrency/thread.rs | 14 ++++++++------ src/tools/tidy/src/deps.rs | 2 ++ 10 files changed, 50 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7337901bc3a59..6fd05bf3d6282 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -781,9 +781,9 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e" +checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" dependencies = [ "nix", "windows-sys", @@ -2357,14 +2357,13 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "nix" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.3.3", "cfg-if", "libc", - "static_assertions", ] [[package]] @@ -3468,6 +3467,7 @@ dependencies = [ name = "rustc_driver_impl" version = "0.0.0" dependencies = [ + "ctrlc", "libc", "rustc_ast", "rustc_ast_lowering", diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index e5dd5729d8905..bae96dbfc3e24 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -134,6 +134,8 @@ const_eval_interior_mutable_data_refer = This would make multiple uses of a constant to be able to see different values and allow circumventing the `Send` and `Sync` requirements for shared mutable data, which is unsound. +const_eval_interrupted = compilation was interrupted + const_eval_invalid_align = align has to be a power of 2 diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 4c7e9194401ac..72cf8bc1958be 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -1,8 +1,10 @@ use crate::const_eval::CheckAlignment; use crate::errors::ConstEvalError; +use std::sync::atomic::Ordering::Relaxed; use either::{Left, Right}; +use rustc_data_structures::CTRL_C_RECEIVED; use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::mir::interpret::{ErrorHandled, InterpErrorInfo}; @@ -63,7 +65,11 @@ fn eval_body_using_ecx<'mir, 'tcx>( )?; // The main interpreter loop. - while ecx.step()? {} + while ecx.step()? { + if CTRL_C_RECEIVED.load(Relaxed) { + throw_exhaust!(Interrupted); + } + } // Intern the result let intern_kind = if cid.promoted.is_some() { diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 4362cae7ed746..2880c52eec47f 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -900,6 +900,7 @@ impl ReportErrorExt for ResourceExhaustionInfo { ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached, ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted, ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full, + ResourceExhaustionInfo::Interrupted => const_eval_interrupted, } } fn add_args(self, _: &Handler, _: &mut DiagnosticBuilder<'_, G>) {} diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index bee5a89c4c737..572460edb1f47 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -47,6 +47,8 @@ extern crate cfg_if; #[macro_use] extern crate rustc_macros; +use std::sync::atomic::AtomicBool; + pub use rustc_index::static_assert_size; #[inline(never)] @@ -129,3 +131,8 @@ impl Drop for OnDrop { // See comments in src/librustc_middle/lib.rs #[doc(hidden)] pub fn __noop_fix_for_27438() {} + +/// `rustc_driver::main` installs a handler that will set this to `true` if +/// the compiler has been sent a request to shut down, such as by a Ctrl-C. +/// This static is placed here so that it is available to all parts of the compiler. +pub static CTRL_C_RECEIVED: AtomicBool = AtomicBool::new(false); diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index a7b01618ade39..2632539485445 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] time = { version = "0.3", default-features = false, features = ["formatting", ] } +ctrlc = "3.4.1" tracing = { version = "0.1.35" } serde_json = "1.0.59" rustc_log = { path = "../rustc_log" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 841c626d0a33a..db674d62b6208 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -25,6 +25,7 @@ use rustc_data_structures::profiling::{ get_resident_set_size, print_time_passes_entry, TimePassesFormat, }; use rustc_data_structures::sync::SeqCst; +use rustc_data_structures::CTRL_C_RECEIVED; use rustc_errors::registry::{InvalidErrorCode, Registry}; use rustc_errors::{markdown, ColorConfig}; use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, PResult, SubdiagnosticMessage}; @@ -1518,6 +1519,19 @@ pub fn main() -> ! { signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ()); + + ctrlc::set_handler(move || { + // Indicate that we have been signaled to stop. If we were already signaled, exit + // immediately. In our interpreter loop we try to consult this value often, but if for + // whatever reason we don't get to that check or the cleanup we do upon finding that + // this bool has become true takes a long time, the exit here will promptly exit the + // process on the second Ctrl-C. + if CTRL_C_RECEIVED.swap(true, Ordering::Relaxed) { + std::process::exit(1); + } + }) + .expect("Unable to install ctrlc handler"); + let exit_code = catch_with_exit_code(|| { let args = env::args_os() .enumerate() diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index e6ef5a41ee0c6..6c2df6ced4015 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -442,6 +442,8 @@ pub enum ResourceExhaustionInfo { MemoryExhausted, /// The address space (of the target) is full. AddressSpaceFull, + /// The compiler got an interrupt signal (a user ran out of patience). + Interrupted, } /// A trait for machine-specific errors (or other "machine stop" conditions). diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 9c11ad85aefd3..343b682b761c0 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -3,13 +3,14 @@ use std::cell::RefCell; use std::collections::hash_map::Entry; use std::num::TryFromIntError; -use std::sync::atomic::{AtomicBool, Ordering::Relaxed}; +use std::sync::atomic::Ordering::Relaxed; use std::task::Poll; use std::time::{Duration, SystemTime}; use log::trace; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::CTRL_C_RECEIVED; use rustc_hir::def_id::DefId; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::Mutability; @@ -1020,21 +1021,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program /// termination). fn run_threads(&mut self) -> InterpResult<'tcx, !> { - static SIGNALED: AtomicBool = AtomicBool::new(false); + // In normal rustc, rustc_driver::main installs this handler. But we don't use that + // function, see src/bin/miri.rs. ctrlc::set_handler(move || { - // Indicate that we have ben signaled to stop. If we were already signaled, exit + // Indicate that we have been signaled to stop. If we were already signaled, exit // immediately. In our interpreter loop we try to consult this value often, but if for // whatever reason we don't get to that check or the cleanup we do upon finding that // this bool has become true takes a long time, the exit here will promptly exit the // process on the second Ctrl-C. - if SIGNALED.swap(true, Relaxed) { + if CTRL_C_RECEIVED.swap(true, Relaxed) { std::process::exit(1); } }) - .unwrap(); + .expect("Unable to install ctrlc handler"); let this = self.eval_context_mut(); loop { - if SIGNALED.load(Relaxed) { + if CTRL_C_RECEIVED.load(Relaxed) { this.machine.handle_abnormal_termination(); std::process::exit(1); } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 410852b6a31f3..df997cd414633 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -137,6 +137,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "crossbeam-utils", "crypto-common", "cstr", + "ctrlc", "darling", "darling_core", "darling_macro", @@ -198,6 +199,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "memmap2", "memoffset", "miniz_oxide", + "nix", "nu-ansi-term", "num_cpus", "object", From a8b0e44e86c944350b2064f5c0f297346bf0c32c Mon Sep 17 00:00:00 2001 From: Fulgen301 Date: Sun, 3 Sep 2023 17:04:42 +0200 Subject: [PATCH 9/9] Command::spawn: Fix STARTUPINFOW.cb being initialized with the address of size_of --- library/std/src/sys/windows/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 6f46da1748a70..84a75d213052f 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -352,7 +352,7 @@ impl Command { }; si_ptr = &mut si_ex as *mut _ as _; } else { - si.cb = mem::size_of:: as c::DWORD; + si.cb = mem::size_of::() as c::DWORD; si_ptr = &mut si as *mut _ as _; }