diff --git a/Cargo.lock b/Cargo.lock index 84a668b5188ce..3103047e75391 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -809,9 +809,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 0.48.0", @@ -2410,14 +2410,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]] @@ -3552,6 +3551,7 @@ dependencies = [ name = "rustc_driver_impl" version = "0.0.0" dependencies = [ + "ctrlc", "libc", "rustc_ast", "rustc_ast_lowering", @@ -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/RELEASES.md b/RELEASES.md index 242b1c2eefd28..c5ac070b317b3 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::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::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/) 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/) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 020402fe25e99..76e3ff0946430 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 fc0dba6b67bc3..e8cb23f115806 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}; @@ -64,7 +66,11 @@ fn eval_body_using_ecx<'mir, 'tcx>( ecx.storage_live_for_always_live_locals()?; // 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 c74fed0e47f52..37d8e3acf3109 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -901,6 +901,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 1a16759d7f9a8..6f3084aeda5cc 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}; @@ -1459,6 +1460,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 577cd20b74ca7..1d8056ef9821d 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -444,6 +444,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/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index f46cf0dc0ff1b..95dced644e161 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -720,32 +720,31 @@ 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(); 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!( + "`&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, so a wildcard `_` is necessary to match exhaustively")); } } } 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/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" } 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 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 _; } 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", 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..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 @@ -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, 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 46ee8d5179e6b..7b8bdfe0053ae 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, 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/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/issue-105479-str-non-exhaustiveness.rs b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.rs new file mode 100644 index 0000000000000..0ee7856c6803a --- /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..771fc320a13f6 --- /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..da8bbdffbf6d5 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" => {}, 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..9fbd871db7c9d --- /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, 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 => {}, +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..4e7f3098ab482 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, 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", @@ -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 {