From 75b6ec980059292faa9cdf538b552faf6b70fb29 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Jun 2024 15:44:13 +1000 Subject: Avoid comments that describe multiple `use` items. There are some comments describing multiple subsequent `use` items. When the big `use` reformatting happens some of these `use` items will be reordered, possibly moving them away from the comment. With this additional level of formatting it's not really feasible to have comments of this type. This commit removes them in various ways: - merging separate `use` items when appropriate; - inserting blank lines between the comment and the first `use` item; - outright deletion (for comments that are relatively low-value); - adding a separate "top-level" comment. We also entirely skip formatting for four library files that contain nothing but `pub use` re-exports, where reordering would be painful. --- compiler/rustc_pattern_analysis/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'compiler/rustc_pattern_analysis/src') diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index c9590ad06b0..1b4bcb789d2 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -21,9 +21,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } use std::fmt; -// Re-exports to avoid rustc_index version issues. -pub use rustc_index::Idx; -pub use rustc_index::IndexVec; +pub use rustc_index::{Idx, IndexVec}; // re-exported to avoid rustc_index version issues #[cfg(feature = "rustc")] use rustc_middle::ty::Ty; -- cgit 1.4.1-3-g733a5 From 86ce911f90d9498b33738655c8cfed2f637c335a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 13 Jul 2024 18:03:05 +0200 Subject: pattern lowering: make sure we never call user-defined PartialEq instances --- compiler/rustc_middle/src/thir.rs | 11 ++---- compiler/rustc_mir_build/src/build/matches/test.rs | 45 ++++++++-------------- compiler/rustc_pattern_analysis/src/rustc.rs | 18 +++++++-- 3 files changed, 35 insertions(+), 39 deletions(-) (limited to 'compiler/rustc_pattern_analysis/src') diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index c97af68c29e..b80d00719ee 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -783,16 +783,13 @@ pub enum PatKind<'tcx> { }, /// One of the following: - /// * `&str` (represented as a valtree), which will be handled as a string pattern and thus - /// exhaustiveness checking will detect if you use the same string twice in different - /// patterns. + /// * `&str`/`&[u8]` (represented as a valtree), which will be handled as a string/slice pattern + /// and thus exhaustiveness checking will detect if you use the same string/slice twice in + /// different patterns. /// * integer, bool, char or float (represented as a valtree), which will be handled by /// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are /// much simpler. - /// * Opaque constants (represented as `mir::ConstValue`), that must not be matched - /// structurally. So anything that does not derive `PartialEq` and `Eq`. - /// - /// These are always compared with the matched place using (the semantics of) `PartialEq`. + /// * `String`, if `string_deref_patterns` is enabled. Constant { value: mir::Const<'tcx>, }, diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index d29874a5ad4..5aed2537750 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -144,7 +144,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { && tcx.is_lang_item(def.did(), LangItem::String) { if !tcx.features().string_deref_patterns { - bug!( + span_bug!( + test.span, "matching on `String` went through without enabling string_deref_patterns" ); } @@ -432,40 +433,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - match *ty.kind() { - ty::Ref(_, deref_ty, _) => ty = deref_ty, - _ => { - // non_scalar_compare called on non-reference type - let temp = self.temp(ty, source_info.span); - self.cfg.push_assign(block, source_info, temp, Rvalue::Use(expect)); - let ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, ty); - let ref_temp = self.temp(ref_ty, source_info.span); - - self.cfg.push_assign( - block, - source_info, - ref_temp, - Rvalue::Ref(self.tcx.lifetimes.re_erased, BorrowKind::Shared, temp), - ); - expect = Operand::Move(ref_temp); - - let ref_temp = self.temp(ref_ty, source_info.span); - self.cfg.push_assign( - block, - source_info, - ref_temp, - Rvalue::Ref(self.tcx.lifetimes.re_erased, BorrowKind::Shared, val), - ); - val = ref_temp; + // Figure out the type on which we are calling `PartialEq`. This involves an extra wrapping + // reference: we can only compare two `&T`, and then compare_ty will be `T`. + // Make sure that we do *not* call any user-defined code here. + // The only types that can end up here are string and byte literals, + // which have their comparison defined in `core`. + // (Interestingly this means that exhaustiveness analysis relies, for soundness, + // on the `PartialEq` impls for `str` and `[u8]` to b correct!) + let compare_ty = match *ty.kind() { + ty::Ref(_, deref_ty, _) + if deref_ty == self.tcx.types.str_ || deref_ty != self.tcx.types.u8 => + { + deref_ty } - } + _ => span_bug!(source_info.span, "invalid type for non-scalar compare: {}", ty), + }; let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span)); let method = trait_method( self.tcx, eq_def_id, sym::eq, - self.tcx.with_opt_host_effect_param(self.def_id, eq_def_id, [ty, ty]), + self.tcx.with_opt_host_effect_param(self.def_id, eq_def_id, [compare_ty, compare_ty]), ); let bool_ty = self.tcx.types.bool; diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d4dd4dd858c..d17ee8bff50 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -462,7 +462,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { // This is a box pattern. ty::Adt(adt, ..) if adt.is_box() => Struct, ty::Ref(..) => Ref, - _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty), + _ => span_bug!( + pat.span, + "pattern has unexpected type: pat: {:?}, ty: {:?}", + pat.kind, + ty.inner() + ), }; } PatKind::DerefPattern { .. } => { @@ -518,7 +523,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { .map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index())) .collect(); } - _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty), + _ => span_bug!( + pat.span, + "pattern has unexpected type: pat: {:?}, ty: {}", + pat.kind, + ty.inner() + ), } } PatKind::Constant { value } => { @@ -663,7 +673,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } } } - _ => bug!("invalid type for range pattern: {}", ty.inner()), + _ => span_bug!(pat.span, "invalid type for range pattern: {}", ty.inner()), }; fields = vec![]; arity = 0; @@ -674,7 +684,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { Some(length.eval_target_usize(cx.tcx, cx.param_env) as usize) } ty::Slice(_) => None, - _ => span_bug!(pat.span, "bad ty {:?} for slice pattern", ty), + _ => span_bug!(pat.span, "bad ty {} for slice pattern", ty.inner()), }; let kind = if slice.is_some() { SliceKind::VarLen(prefix.len(), suffix.len()) -- cgit 1.4.1-3-g733a5 From aef0e346de744faeaa522b9c08562bb3e1814adc Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 19 Jul 2024 11:51:21 -0400 Subject: Avoid ref when using format! in compiler Clean up a few minor refs in `format!` macro, as it has a performance cost. Apparently the compiler is unable to inline `format!("{}", &variable)`, and does a run-time double-reference instead (format macro already does one level referencing). Inlining format args prevents accidental `&` misuse. --- compiler/rustc_codegen_cranelift/src/abi/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/back/link.rs | 12 +++++----- compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 4 ++-- compiler/rustc_codegen_ssa/src/mono_item.rs | 2 +- compiler/rustc_fluent_macro/src/fluent.rs | 2 +- .../src/errors/wrong_number_of_generic_args.rs | 2 +- .../src/outlives/implicit_infer.rs | 6 ++--- compiler/rustc_hir_typeck/src/method/suggest.rs | 4 ++-- compiler/rustc_middle/src/middle/stability.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/util/find_self_call.rs | 2 +- .../rustc_mir_dataflow/src/impls/initialized.rs | 2 +- .../src/dead_store_elimination.rs | 2 +- .../src/early_otherwise_branch.rs | 4 ++-- compiler/rustc_pattern_analysis/src/constructor.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 6 ++--- compiler/rustc_resolve/src/imports.rs | 2 +- compiler/rustc_resolve/src/rustdoc.rs | 2 +- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 28 +++++++++++----------- compiler/rustc_type_ir/src/const_kind.rs | 10 ++++---- compiler/rustc_type_ir/src/region_kind.rs | 2 +- compiler/rustc_type_ir/src/ty_kind.rs | 16 ++++++------- compiler/stable_mir/src/mir/pretty.rs | 10 ++++---- 23 files changed, 61 insertions(+), 65 deletions(-) (limited to 'compiler/rustc_pattern_analysis/src') diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index fa0de6f9de5..ac5aaea561c 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -505,7 +505,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let nop_inst = fx.bcx.ins().nop(); fx.add_comment( nop_inst, - format!("virtual call; self arg pass mode: {:?}", &fn_abi.args[0]), + format!("virtual call; self arg pass mode: {:?}", fn_abi.args[0]), ); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8e07d128dbd..8c582fac0d8 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -759,7 +759,7 @@ fn link_natively( sess.dcx().abort_if_errors(); // Invoke the system linker - info!("{:?}", &cmd); + info!("{cmd:?}"); let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok(); let unknown_arg_regex = Regex::new(r"(unknown|unrecognized) (command line )?(option|argument)").unwrap(); @@ -796,7 +796,7 @@ fn link_natively( cmd.arg(arg); } } - info!("{:?}", &cmd); + info!("{cmd:?}"); continue; } @@ -817,7 +817,7 @@ fn link_natively( cmd.arg(arg); } } - info!("{:?}", &cmd); + info!("{cmd:?}"); continue; } @@ -878,7 +878,7 @@ fn link_natively( cmd.arg(arg); } } - info!("{:?}", &cmd); + info!("{cmd:?}"); continue; } @@ -996,7 +996,7 @@ fn link_natively( sess.dcx().emit_err(errors::UnableToExeLinker { linker_path, error: e, - command_formatted: format!("{:?}", &cmd), + command_formatted: format!("{cmd:?}"), }); } @@ -1567,7 +1567,7 @@ fn print_native_static_libs( sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts); // Prefix for greppability // Note: This must not be translated as tools are allowed to depend on this exact string. - sess.dcx().note(format!("native-static-libs: {}", &lib_args.join(" "))); + sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" "))); } } } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 56a893738df..bfa4c683d56 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -328,7 +328,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { sym::link_section => { if let Some(val) = attr.value_str() { if val.as_str().bytes().any(|b| b == 0) { - let msg = format!("illegal null byte in link_section value: `{}`", &val); + let msg = format!("illegal null byte in link_section value: `{val}`"); tcx.dcx().span_err(attr.span, msg); } else { codegen_fn_attrs.link_section = Some(val); @@ -726,7 +726,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { if *ordinal <= u16::MAX as u128 { Some(ordinal.get() as u16) } else { - let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal); + let msg = format!("ordinal value in `link_ordinal` is too large: `{ordinal}`"); tcx.dcx() .struct_span_err(attr.span, msg) .with_note("the value may not exceed `u16::MAX`") diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 0fbcb938d1a..559ec400577 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -130,7 +130,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { let symbol_name = self.symbol_name(cx.tcx()).name; - debug!("symbol {}", &symbol_name); + debug!("symbol {symbol_name}"); match *self { MonoItem::Static(def_id) => { diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index 214b6587af3..68fdabd3529 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -253,7 +253,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok for Attribute { id: Identifier { name: attr_name }, .. } in attributes { let snake_name = Ident::new( - &format!("{}{}", &crate_prefix, &attr_name.replace('-', "_")), + &format!("{crate_prefix}{}", attr_name.replace('-', "_")), resource_str.span(), ); if !previous_attrs.insert(snake_name.clone()) { diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index 6426ad9dc18..10be69a9fbb 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -651,7 +651,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { self.path_segment.hir_id, num_params_to_take, ); - debug!("suggested_args: {:?}", &suggested_args); + debug!("suggested_args: {suggested_args:?}"); match self.angle_brackets { AngleBrackets::Missing => { diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index af08f50f655..d953736c28c 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -249,7 +249,7 @@ fn check_explicit_predicates<'tcx>( let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id); for (outlives_predicate, &span) in explicit_predicates.as_ref().skip_binder() { - debug!("outlives_predicate = {:?}", &outlives_predicate); + debug!("outlives_predicate = {outlives_predicate:?}"); // Careful: If we are inferring the effects of a `dyn Trait<..>` // type, then when we look up the predicates for `Trait`, @@ -289,12 +289,12 @@ fn check_explicit_predicates<'tcx>( && let GenericArgKind::Type(ty) = outlives_predicate.0.unpack() && ty.walk().any(|arg| arg == self_ty.into()) { - debug!("skipping self ty = {:?}", &ty); + debug!("skipping self ty = {ty:?}"); continue; } let predicate = explicit_predicates.rebind(*outlives_predicate).instantiate(tcx, args); - debug!("predicate = {:?}", &predicate); + debug!("predicate = {predicate:?}"); insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates); } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1cc7cf67ee3..9bb30780a6e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1265,9 +1265,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ( match parent_pred { - None => format!("`{}`", &p), + None => format!("`{p}`"), Some(parent_pred) => match format_pred(*parent_pred) { - None => format!("`{}`", &p), + None => format!("`{p}`"), Some((parent_p, _)) => { if !suggested && !suggested_bounds.contains(pred) diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index d1ccd158cf9..b113e81bd2d 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -112,7 +112,7 @@ pub fn report_unstable( ) { let msg = match reason { Some(r) => format!("use of unstable library feature '{feature}': {r}"), - None => format!("use of unstable library feature '{}'", &feature), + None => format!("use of unstable library feature '{feature}'"), }; if is_soft { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 57cd2dc73c4..0e241663e18 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2627,7 +2627,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { self.prepare_region_info(value); } - debug!("self.used_region_names: {:?}", &self.used_region_names); + debug!("self.used_region_names: {:?}", self.used_region_names); let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs index 027e2703e98..831853b0b48 100644 --- a/compiler/rustc_middle/src/util/find_self_call.rs +++ b/compiler/rustc_middle/src/util/find_self_call.rs @@ -14,7 +14,7 @@ pub fn find_self_call<'tcx>( local: Local, block: BasicBlock, ) -> Option<(DefId, GenericArgsRef<'tcx>)> { - debug!("find_self_call(local={:?}): terminator={:?}", local, &body[block].terminator); + debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator); if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) = &body[block].terminator { diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index a9bceeccdce..d44da42416d 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -688,7 +688,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> { let init_loc_map = &move_data.init_loc_map; let rev_lookup = &move_data.rev_lookup; - debug!("initializes move_indexes {:?}", &init_loc_map[location]); + debug!("initializes move_indexes {:?}", init_loc_map[location]); trans.gen_all(init_loc_map[location].iter().copied()); if let mir::StatementKind::StorageDead(local) = stmt.kind { diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 08dba1de500..60230bea02e 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -102,7 +102,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { | StatementKind::Nop => (), StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => { - bug!("{:?} not found in this MIR phase!", &statement.kind) + bug!("{:?} not found in this MIR phase!", statement.kind) } } } diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 9edb8bcee6e..40c0c723d25 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -106,11 +106,11 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { let parent = BasicBlock::from_usize(i); let Some(opt_data) = evaluate_candidate(tcx, body, parent) else { continue }; - if !tcx.consider_optimizing(|| format!("EarlyOtherwiseBranch {:?}", &opt_data)) { + if !tcx.consider_optimizing(|| format!("EarlyOtherwiseBranch {opt_data:?}")) { break; } - trace!("SUCCESS: found optimization possibility to apply: {:?}", &opt_data); + trace!("SUCCESS: found optimization possibility to apply: {opt_data:?}"); should_cleanup = true; diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index fb103705475..f3e8e547066 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -904,7 +904,7 @@ impl Constructor { // be careful to detect strings here. However a string literal pattern will never // be reported as a non-exhaustiveness witness, so we can ignore this issue. Ref => { - write!(f, "&{:?}", &fields.next().unwrap())?; + write!(f, "&{:?}", fields.next().unwrap())?; } Slice(slice) => { write!(f, "[")?; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7c0405c87e0..bf7972e392c 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { BuiltinLintDiag::AmbiguousGlobImports { diag }, ); } else { - let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", &diag.msg); + let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", diag.msg); report_ambiguity_error(&mut err, diag); err.emit(); } @@ -798,7 +798,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } ResolutionError::FailedToResolve { segment, label, suggestion, module } => { let mut err = - struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {}", &label); + struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {label}"); err.span_label(span, label); if let Some((suggestions, msg, applicability)) = suggestion { @@ -2893,7 +2893,7 @@ fn show_candidates( "" }; candidate.0 = - format!("{add_use}{}{append}{trailing}{additional_newline}", &candidate.0); + format!("{add_use}{}{append}{trailing}{additional_newline}", candidate.0); } match mode { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 3896fe4c4fa..d05326ee311 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -694,7 +694,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .collect::>(); let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),); - let mut diag = struct_span_code_err!(self.dcx(), span, E0432, "{}", &msg); + let mut diag = struct_span_code_err!(self.dcx(), span, E0432, "{msg}"); if let Some((_, UnresolvedImportError { note: Some(note), .. })) = errors.iter().last() { diag.note(note.clone()); diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 59460815321..4c49c15c472 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -339,7 +339,7 @@ pub fn strip_generics_from_path(path_str: &str) -> Result, MalformedGen } } - debug!("path_str: {:?}\nstripped segments: {:?}", path_str, &stripped_segments); + debug!("path_str: {path_str:?}\nstripped segments: {stripped_segments:?}"); let stripped_path = stripped_segments.join("::"); diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index f998fd599b7..190ea443189 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -238,12 +238,12 @@ fn encode_predicate<'tcx>( match predicate.as_ref().skip_binder() { ty::ExistentialPredicate::Trait(trait_ref) => { let name = encode_ty_name(tcx, trait_ref.def_id); - let _ = write!(s, "u{}{}", name.len(), &name); + let _ = write!(s, "u{}{}", name.len(), name); s.push_str(&encode_args(tcx, trait_ref.args, trait_ref.def_id, true, dict, options)); } ty::ExistentialPredicate::Projection(projection) => { let name = encode_ty_name(tcx, projection.def_id); - let _ = write!(s, "u{}{}", name.len(), &name); + let _ = write!(s, "u{}{}", name.len(), name); s.push_str(&encode_args(tcx, projection.args, projection.def_id, true, dict, options)); match projection.term.unpack() { TermKind::Ty(ty) => s.push_str(&encode_ty(tcx, ty, dict, options)), @@ -258,7 +258,7 @@ fn encode_predicate<'tcx>( } ty::ExistentialPredicate::AutoTrait(def_id) => { let name = encode_ty_name(tcx, *def_id); - let _ = write!(s, "u{}{}", name.len(), &name); + let _ = write!(s, "u{}{}", name.len(), name); } }; compress(dict, DictKey::Predicate(*predicate.as_ref().skip_binder()), &mut s); @@ -416,7 +416,7 @@ pub fn encode_ty<'tcx>( // A let len = len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()); let mut s = String::from("A"); - let _ = write!(s, "{}", &len); + let _ = write!(s, "{len}"); s.push_str(&encode_ty(tcx, *ty0, dict, options)); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); @@ -492,13 +492,13 @@ pub fn encode_ty<'tcx>( // calling convention (or extern types [i.e., ty::Foreign]) as , where // is . let name = tcx.item_name(def_id).to_string(); - let _ = write!(s, "{}{}", name.len(), &name); + let _ = write!(s, "{}{}", name.len(), name); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); } else { // u[IE], where is // , as vendor extended type. let name = encode_ty_name(tcx, def_id); - let _ = write!(s, "u{}{}", name.len(), &name); + let _ = write!(s, "u{}{}", name.len(), name); s.push_str(&encode_args(tcx, args, def_id, false, dict, options)); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); } @@ -530,7 +530,7 @@ pub fn encode_ty<'tcx>( } } else { let name = tcx.item_name(*def_id).to_string(); - let _ = write!(s, "{}{}", name.len(), &name); + let _ = write!(s, "{}{}", name.len(), name); } compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); @@ -542,7 +542,7 @@ pub fn encode_ty<'tcx>( // as vendor extended type. let mut s = String::new(); let name = encode_ty_name(tcx, *def_id); - let _ = write!(s, "u{}{}", name.len(), &name); + let _ = write!(s, "u{}{}", name.len(), name); s.push_str(&encode_args(tcx, args, *def_id, false, dict, options)); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); @@ -553,7 +553,7 @@ pub fn encode_ty<'tcx>( // as vendor extended type. let mut s = String::new(); let name = encode_ty_name(tcx, *def_id); - let _ = write!(s, "u{}{}", name.len(), &name); + let _ = write!(s, "u{}{}", name.len(), name); let parent_args = tcx.mk_args(args.as_coroutine_closure().parent_args()); s.push_str(&encode_args(tcx, parent_args, *def_id, false, dict, options)); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); @@ -565,7 +565,7 @@ pub fn encode_ty<'tcx>( // as vendor extended type. let mut s = String::new(); let name = encode_ty_name(tcx, *def_id); - let _ = write!(s, "u{}{}", name.len(), &name); + let _ = write!(s, "u{}{}", name.len(), name); // Encode parent args only s.push_str(&encode_args( tcx, @@ -588,7 +588,7 @@ pub fn encode_ty<'tcx>( s.push('E'); compress(dict, DictKey::Ty(Ty::new_imm_ref(tcx, *region, *ty0), TyQ::None), &mut s); if ty.is_mutable_ptr() { - s = format!("{}{}", "U3mut", &s); + s = format!("{}{}", "U3mut", s); compress(dict, DictKey::Ty(ty, TyQ::Mut), &mut s); } typeid.push_str(&s); @@ -600,10 +600,10 @@ pub fn encode_ty<'tcx>( let mut s = String::new(); s.push_str(&encode_ty(tcx, *ptr_ty, dict, options)); if !ty.is_mutable_ptr() { - s = format!("{}{}", "K", &s); + s = format!("{}{}", "K", s); compress(dict, DictKey::Ty(*ptr_ty, TyQ::Const), &mut s); }; - s = format!("{}{}", "P", &s); + s = format!("{}{}", "P", s); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); } @@ -722,7 +722,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { s.push('C'); s.push_str(&to_disambiguator(tcx.stable_crate_id(def_path.krate).as_u64())); let crate_name = tcx.crate_name(def_path.krate).to_string(); - let _ = write!(s, "{}{}", crate_name.len(), &crate_name); + let _ = write!(s, "{}{}", crate_name.len(), crate_name); // Disambiguators and names def_path.data.reverse(); diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index f1683f5449f..1a51c95ecdf 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -65,15 +65,13 @@ impl fmt::Debug for ConstKind { match self { Param(param) => write!(f, "{param:?}"), - Infer(var) => write!(f, "{:?}", &var), + Infer(var) => write!(f, "{var:?}"), Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var), Placeholder(placeholder) => write!(f, "{placeholder:?}"), - Unevaluated(uv) => { - write!(f, "{:?}", &uv) - } - Value(ty, valtree) => write!(f, "({valtree:?}: {:?})", &ty), + Unevaluated(uv) => write!(f, "{uv:?}"), + Value(ty, valtree) => write!(f, "({valtree:?}: {ty:?})"), Error(_) => write!(f, "{{const error}}"), - Expr(expr) => write!(f, "{:?}", &expr), + Expr(expr) => write!(f, "{expr:?}"), } } } diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 7abcc370c88..140c89af147 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -232,7 +232,7 @@ impl fmt::Debug for RegionKind { ReStatic => f.write_str("'static"), - ReVar(vid) => write!(f, "{:?}", &vid), + ReVar(vid) => write!(f, "{vid:?}"), RePlaceholder(placeholder) => write!(f, "{placeholder:?}"), diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 4ffebef9f1f..9896425a341 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -367,18 +367,16 @@ impl fmt::Debug for TyKind { } Foreign(d) => f.debug_tuple("Foreign").field(d).finish(), Str => write!(f, "str"), - Array(t, c) => write!(f, "[{:?}; {:?}]", &t, &c), - Pat(t, p) => write!(f, "pattern_type!({:?} is {:?})", &t, &p), + Array(t, c) => write!(f, "[{t:?}; {c:?}]"), + Pat(t, p) => write!(f, "pattern_type!({t:?} is {p:?})"), Slice(t) => write!(f, "[{:?}]", &t), RawPtr(ty, mutbl) => write!(f, "*{} {:?}", mutbl.ptr_str(), ty), Ref(r, t, m) => write!(f, "&{:?} {}{:?}", r, m.prefix_str(), t), FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&s).finish(), - FnPtr(s) => write!(f, "{:?}", &s), + FnPtr(s) => write!(f, "{s:?}"), Dynamic(p, r, repr) => match repr { - DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &p, &r), - DynKind::DynStar => { - write!(f, "dyn* {:?} + {:?}", &p, &r) - } + DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"), + DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"), }, Closure(d, s) => f.debug_tuple("Closure").field(d).field(&s).finish(), CoroutineClosure(d, s) => f.debug_tuple("CoroutineClosure").field(d).field(&s).finish(), @@ -392,7 +390,7 @@ impl fmt::Debug for TyKind { if count > 0 { write!(f, ", ")?; } - write!(f, "{:?}", &ty)?; + write!(f, "{ty:?}")?; count += 1; } // unary tuples need a trailing comma @@ -1050,7 +1048,7 @@ impl fmt::Debug for FnSig { if i > 0 { write!(f, ", ")?; } - write!(f, "{:?}", &ty)?; + write!(f, "{ty:?}")?; } if *c_variadic { if inputs.is_empty() { diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 83734a0d138..18ecccb4536 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -179,7 +179,7 @@ fn pretty_terminator_head(writer: &mut W, terminator: &TerminatorKind) if !expected { write!(writer, "!")?; } - write!(writer, "{}, ", &pretty_operand(cond))?; + write!(writer, "{}, ", pretty_operand(cond))?; pretty_assert_message(writer, msg)?; write!(writer, ")") } @@ -325,7 +325,7 @@ fn pretty_ty_const(ct: &TyConst) -> String { fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { match rval { Rvalue::AddressOf(mutability, place) => { - write!(writer, "&raw {}(*{:?})", &pretty_mut(*mutability), place) + write!(writer, "&raw {}(*{:?})", pretty_mut(*mutability), place) } Rvalue::Aggregate(aggregate_kind, operands) => { // FIXME: Add pretty_aggregate function that returns a pretty string @@ -336,13 +336,13 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { write!(writer, ")") } Rvalue::BinaryOp(bin, op1, op2) => { - write!(writer, "{:?}({}, {})", bin, &pretty_operand(op1), pretty_operand(op2)) + write!(writer, "{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2)) } Rvalue::Cast(_, op, ty) => { write!(writer, "{} as {}", pretty_operand(op), ty) } Rvalue::CheckedBinaryOp(bin, op1, op2) => { - write!(writer, "Checked{:?}({}, {})", bin, &pretty_operand(op1), pretty_operand(op2)) + write!(writer, "Checked{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2)) } Rvalue::CopyForDeref(deref) => { write!(writer, "CopyForDeref({:?})", deref) @@ -363,7 +363,7 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { write!(writer, "{kind}{:?}", place) } Rvalue::Repeat(op, cnst) => { - write!(writer, "{} \" \" {}", &pretty_operand(op), &pretty_ty_const(cnst)) + write!(writer, "{} \" \" {}", pretty_operand(op), pretty_ty_const(cnst)) } Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::ThreadLocalRef(item) => { -- cgit 1.4.1-3-g733a5 From 670723e6fba094fa613082261ad89de387af7939 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 20 Jul 2024 22:18:35 +0200 Subject: Expand or-patterns as a separate step --- compiler/rustc_pattern_analysis/src/pat.rs | 13 +- compiler/rustc_pattern_analysis/src/usefulness.rs | 180 +++++++++------------- 2 files changed, 86 insertions(+), 107 deletions(-) (limited to 'compiler/rustc_pattern_analysis/src') diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 5e75976621e..e8d6c542c5f 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -190,7 +190,18 @@ impl<'p, Cx: PatCx> PatOrWild<'p, Cx> { } } - /// Expand this (possibly-nested) or-pattern into its alternatives. + /// Expand this or-pattern into its alternatives. This only expands one or-pattern; use + /// `flatten_or_pat` to recursively expand nested or-patterns. + pub(crate) fn expand_or_pat(self) -> SmallVec<[Self; 1]> { + match self { + PatOrWild::Pat(pat) if pat.is_or_pat() => { + pat.iter_fields().map(|ipat| PatOrWild::Pat(&ipat.pat)).collect() + } + _ => smallvec![self], + } + } + + /// Recursively expand this (possibly-nested) or-pattern into its alternatives. pub(crate) fn flatten_or_pat(self) -> SmallVec<[Self; 1]> { match self { PatOrWild::Pat(pat) if pat.is_or_pat() => pat diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 6e96a93473f..8486792b554 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -462,8 +462,9 @@ //! # Or-patterns //! //! What we have described so far works well if there are no or-patterns. To handle them, if the -//! first pattern of a row in the matrix is an or-pattern, we expand it by duplicating the rest of -//! the row as necessary. This is handled automatically in [`Matrix`]. +//! first pattern of any row in the matrix is an or-pattern, we expand it by duplicating the rest of +//! the row as necessary. For code reuse, this is implemented as "specializing with the `Or` +//! constructor". //! //! This makes usefulness tracking subtle, because we also want to compute whether an alternative of //! an or-pattern is redundant, e.g. in `Some(_) | Some(0)`. We therefore track usefulness of each @@ -875,6 +876,11 @@ impl PlaceInfo { return Ok((smallvec![Constructor::PrivateUninhabited], vec![])); } + if ctors.clone().any(|c| matches!(c, Constructor::Or)) { + // If any constructor is `Or`, we expand or-patterns. + return Ok((smallvec![Constructor::Or], vec![])); + } + let ctors_for_ty = cx.ctors_for_ty(&self.ty)?; debug!(?ctors_for_ty); @@ -968,10 +974,6 @@ impl<'p, Cx: PatCx> PatStack<'p, Cx> { PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true } } - fn is_empty(&self) -> bool { - self.pats.is_empty() - } - fn len(&self) -> usize { self.pats.len() } @@ -984,10 +986,10 @@ impl<'p, Cx: PatCx> PatStack<'p, Cx> { self.pats.iter().copied() } - // Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is - // an or-pattern. Panics if `self` is empty. + // Expand the first or-pattern into its subpatterns. Only useful if the pattern is an + // or-pattern. Panics if `self` is empty. fn expand_or_pat(&self) -> impl Iterator> + Captures<'_> { - self.head().flatten_or_pat().into_iter().map(move |pat| { + self.head().expand_or_pat().into_iter().map(move |pat| { let mut new = self.clone(); new.pats[0] = pat; new @@ -1057,10 +1059,6 @@ struct MatrixRow<'p, Cx: PatCx> { } impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { - fn is_empty(&self) -> bool { - self.pats.is_empty() - } - fn len(&self) -> usize { self.pats.len() } @@ -1073,12 +1071,14 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { self.pats.iter() } - // Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is - // an or-pattern. Panics if `self` is empty. - fn expand_or_pat(&self) -> impl Iterator> + Captures<'_> { - self.pats.expand_or_pat().map(|patstack| MatrixRow { + // Expand the first or-pattern (if any) into its subpatterns. Panics if `self` is empty. + fn expand_or_pat( + &self, + parent_row: usize, + ) -> impl Iterator> + Captures<'_> { + self.pats.expand_or_pat().map(move |patstack| MatrixRow { pats: patstack, - parent_row: self.parent_row, + parent_row, is_under_guard: self.is_under_guard, useful: false, intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`. @@ -1100,7 +1100,7 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { parent_row, is_under_guard: self.is_under_guard, useful: false, - intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`. + intersects: BitSet::new_empty(0), // Initialized in `Matrix::push`. }) } } @@ -1116,7 +1116,7 @@ impl<'p, Cx: PatCx> fmt::Debug for MatrixRow<'p, Cx> { /// Invariant: each row must have the same length, and each column must have the same type. /// /// Invariant: the first column must not contain or-patterns. This is handled by -/// [`Matrix::expand_and_push`]. +/// [`Matrix::push`]. /// /// In fact each column corresponds to a place inside the scrutinee of the match. E.g. after /// specializing `(,)` and `Some` on a pattern of type `(Option, bool)`, the first column of @@ -1136,19 +1136,10 @@ struct Matrix<'p, Cx: PatCx> { } impl<'p, Cx: PatCx> Matrix<'p, Cx> { - /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively - /// expands it. Internal method, prefer [`Matrix::new`]. - fn expand_and_push(&mut self, mut row: MatrixRow<'p, Cx>) { - if !row.is_empty() && row.head().is_or_pat() { - // Expand nested or-patterns. - for mut new_row in row.expand_or_pat() { - new_row.intersects = BitSet::new_empty(self.rows.len()); - self.rows.push(new_row); - } - } else { - row.intersects = BitSet::new_empty(self.rows.len()); - self.rows.push(row); - } + /// Pushes a new row to the matrix. Internal method, prefer [`Matrix::new`]. + fn push(&mut self, mut row: MatrixRow<'p, Cx>) { + row.intersects = BitSet::new_empty(self.rows.len()); + self.rows.push(row); } /// Build a new matrix from an iterator of `MatchArm`s. @@ -1170,9 +1161,9 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> { parent_row: arm_id, is_under_guard: arm.has_guard, useful: false, - intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`. + intersects: BitSet::new_empty(0), // Initialized in `Matrix::push`. }; - matrix.expand_and_push(v); + matrix.push(v); } matrix } @@ -1209,22 +1200,38 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> { ctor: &Constructor, ctor_is_relevant: bool, ) -> Result, Cx::Error> { - let subfield_place_info = self.place_info[0].specialize(pcx.cx, ctor); - let arity = subfield_place_info.len(); - let specialized_place_info = - subfield_place_info.chain(self.place_info[1..].iter().cloned()).collect(); - let mut matrix = Matrix { - rows: Vec::new(), - place_info: specialized_place_info, - wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant, - }; - for (i, row) in self.rows().enumerate() { - if ctor.is_covered_by(pcx.cx, row.head().ctor())? { - let new_row = row.pop_head_constructor(pcx.cx, ctor, arity, ctor_is_relevant, i)?; - matrix.expand_and_push(new_row); + if matches!(ctor, Constructor::Or) { + // Specializing with `Or` means expanding rows with or-patterns. + let mut matrix = Matrix { + rows: Vec::new(), + place_info: self.place_info.clone(), + wildcard_row_is_relevant: self.wildcard_row_is_relevant, + }; + for (i, row) in self.rows().enumerate() { + for new_row in row.expand_or_pat(i) { + matrix.push(new_row); + } } + Ok(matrix) + } else { + let subfield_place_info = self.place_info[0].specialize(pcx.cx, ctor); + let arity = subfield_place_info.len(); + let specialized_place_info = + subfield_place_info.chain(self.place_info[1..].iter().cloned()).collect(); + let mut matrix = Matrix { + rows: Vec::new(), + place_info: specialized_place_info, + wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant, + }; + for (i, row) in self.rows().enumerate() { + if ctor.is_covered_by(pcx.cx, row.head().ctor())? { + let new_row = + row.pop_head_constructor(pcx.cx, ctor, arity, ctor_is_relevant, i)?; + matrix.push(new_row); + } + } + Ok(matrix) } - Ok(matrix) } /// Recover row usefulness and intersection information from a processed specialized matrix. @@ -1465,7 +1472,9 @@ impl WitnessMatrix { missing_ctors: &[Constructor], ctor: &Constructor, ) { - if self.is_empty() { + // The `Or` constructor indicates that we expanded or-patterns. This doesn't affect + // witnesses. + if self.is_empty() || matches!(ctor, Constructor::Or) { return; } if matches!(ctor, Constructor::Missing) { @@ -1715,48 +1724,6 @@ pub enum Usefulness<'p, Cx: PatCx> { Redundant, } -/// Report whether this pattern was found useful, and its subpatterns that were not useful if any. -fn collect_pattern_usefulness<'p, Cx: PatCx>( - useful_subpatterns: &FxHashSet, - pat: &'p DeconstructedPat, -) -> Usefulness<'p, Cx> { - fn pat_is_useful<'p, Cx: PatCx>( - useful_subpatterns: &FxHashSet, - pat: &'p DeconstructedPat, - ) -> bool { - if useful_subpatterns.contains(&pat.uid) { - true - } else if pat.is_or_pat() - && pat.iter_fields().any(|f| pat_is_useful(useful_subpatterns, &f.pat)) - { - // We always expand or patterns in the matrix, so we will never see the actual - // or-pattern (the one with constructor `Or`) in the column. As such, it will not be - // marked as useful itself, only its children will. We recover this information here. - true - } else { - false - } - } - - let mut redundant_subpats = Vec::new(); - pat.walk(&mut |p| { - if pat_is_useful(useful_subpatterns, p) { - // The pattern is useful, so we recurse to find redundant subpatterns. - true - } else { - // The pattern is redundant. - redundant_subpats.push(p); - false // stop recursing - } - }); - - if pat_is_useful(useful_subpatterns, pat) { - Usefulness::Useful(redundant_subpats) - } else { - Usefulness::Redundant - } -} - /// The output of checking a match for exhaustiveness and arm usefulness. pub struct UsefulnessReport<'p, Cx: PatCx> { /// For each arm of the input, whether that arm is useful after the arms above it. @@ -1793,25 +1760,26 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>( .copied() .map(|arm| { debug!(?arm); - let usefulness = collect_pattern_usefulness(&cx.useful_subpatterns, arm.pat); + let usefulness = if cx.useful_subpatterns.contains(&arm.pat.uid) { + let mut redundant_subpats = Vec::new(); + arm.pat.walk(&mut |subpat| { + if cx.useful_subpatterns.contains(&subpat.uid) { + true // keep recursing + } else { + redundant_subpats.push(subpat); + false // stop recursing + } + }); + Usefulness::Useful(redundant_subpats) + } else { + Usefulness::Redundant + }; debug!(?usefulness); (arm, usefulness) }) .collect(); - let mut arm_intersections: Vec<_> = - arms.iter().enumerate().map(|(i, _)| BitSet::new_empty(i)).collect(); - for row in matrix.rows() { - let arm_id = row.parent_row; - for intersection in row.intersects.iter() { - // Convert the matrix row ids into arm ids (they can differ because we expand or-patterns). - let arm_intersection = matrix.rows[intersection].parent_row; - // Note: self-intersection can happen with or-patterns. - if arm_intersection != arm_id { - arm_intersections[arm_id].insert(arm_intersection); - } - } - } + let arm_intersections: Vec<_> = matrix.rows().map(|row| row.intersects.clone()).collect(); Ok(UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses, arm_intersections }) } -- cgit 1.4.1-3-g733a5 From 710add58e2063616770ec8893e41b3179ad23d31 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 21 Jul 2024 15:17:29 +0200 Subject: Tweak `collect_non_exhaustive_tys` --- .../src/thir/pattern/check_match.rs | 32 +++++++++++----------- compiler/rustc_pattern_analysis/src/rustc.rs | 8 +++++- 2 files changed, 23 insertions(+), 17 deletions(-) (limited to 'compiler/rustc_pattern_analysis/src') 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 70065b5a2c3..38f425581c1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -16,8 +16,8 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_pattern_analysis::errors::Uncovered; use rustc_pattern_analysis::rustc::{ - Constructor, DeconstructedPat, MatchArm, RustcPatCtxt as PatCtxt, Usefulness, UsefulnessReport, - WitnessPat, + Constructor, DeconstructedPat, MatchArm, RevealedTy, RustcPatCtxt as PatCtxt, Usefulness, + UsefulnessReport, WitnessPat, }; use rustc_session::lint::builtin::{ BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS, @@ -998,26 +998,26 @@ fn report_non_exhaustive_match<'p, 'tcx>( err.note(format!("the matched value is of type `{}`", scrut_ty)); if !is_empty_match { - let mut non_exhaustive_tys = FxIndexSet::default(); + let mut special_tys = FxIndexSet::default(); // Look at the first witness. - collect_non_exhaustive_tys(cx, &witnesses[0], &mut non_exhaustive_tys); + collect_special_tys(cx, &witnesses[0], &mut special_tys); - for ty in non_exhaustive_tys { + for ty in special_tys { if ty.is_ptr_sized_integral() { - if ty == cx.tcx.types.usize { + if ty.inner() == cx.tcx.types.usize { err.note(format!( "`{ty}` does not have a fixed maximum value, so half-open ranges are necessary to match \ exhaustively", )); - } else if ty == cx.tcx.types.isize { + } else if ty.inner() == cx.tcx.types.isize { err.note(format!( "`{ty}` does not have fixed minimum and maximum values, so half-open ranges are necessary to match \ exhaustively", )); } - } else if ty == cx.tcx.types.str_ { + } else if ty.inner() == cx.tcx.types.str_ { err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary"); - } else if cx.is_foreign_non_exhaustive_enum(cx.reveal_opaque_ty(ty)) { + } 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")); } } @@ -1168,22 +1168,22 @@ fn joined_uncovered_patterns<'p, 'tcx>( } } -fn collect_non_exhaustive_tys<'tcx>( +/// Collect types that require specific explanations when they show up in witnesses. +fn collect_special_tys<'tcx>( cx: &PatCtxt<'_, 'tcx>, pat: &WitnessPat<'_, 'tcx>, - non_exhaustive_tys: &mut FxIndexSet>, + special_tys: &mut FxIndexSet>, ) { - if matches!(pat.ctor(), Constructor::NonExhaustive) { - non_exhaustive_tys.insert(pat.ty().inner()); + if matches!(pat.ctor(), Constructor::NonExhaustive | Constructor::Never) { + special_tys.insert(*pat.ty()); } if let Constructor::IntRange(range) = pat.ctor() { if cx.is_range_beyond_boundaries(range, *pat.ty()) { // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`. - non_exhaustive_tys.insert(pat.ty().inner()); + special_tys.insert(*pat.ty()); } } - pat.iter_fields() - .for_each(|field_pat| collect_non_exhaustive_tys(cx, field_pat, non_exhaustive_tys)) + pat.iter_fields().for_each(|field_pat| collect_special_tys(cx, field_pat, special_tys)) } fn report_adt_defined_here<'tcx>( diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d17ee8bff50..6ef2d69273e 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -40,9 +40,15 @@ pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat>; /// /// Use `.inner()` or deref to get to the `Ty<'tcx>`. #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct RevealedTy<'tcx>(Ty<'tcx>); +impl<'tcx> fmt::Display for RevealedTy<'tcx> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(fmt) + } +} + impl<'tcx> fmt::Debug for RevealedTy<'tcx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(fmt) -- cgit 1.4.1-3-g733a5 From bab8ede76130b4ca6e1652dbfe2d5d0fb8174495 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 20 Jul 2024 19:08:41 +0200 Subject: Move rustc-specific entrypoint to the `rustc` module --- .../src/thir/pattern/check_match.rs | 16 ++++++---- compiler/rustc_pattern_analysis/src/lib.rs | 37 ++-------------------- compiler/rustc_pattern_analysis/src/rustc.rs | 26 +++++++++++++++ 3 files changed, 39 insertions(+), 40 deletions(-) (limited to 'compiler/rustc_pattern_analysis/src') 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 95799cec94b..28cb994b8e2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -391,12 +391,16 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { ) -> Result, ErrorGuaranteed> { let pattern_complexity_limit = get_limit_size(cx.tcx.hir().krate_attrs(), cx.tcx.sess, sym::pattern_complexity); - let report = - rustc_pattern_analysis::analyze_match(&cx, &arms, scrut_ty, pattern_complexity_limit) - .map_err(|err| { - self.error = Err(err); - err - })?; + let report = rustc_pattern_analysis::rustc::analyze_match( + &cx, + &arms, + scrut_ty, + pattern_complexity_limit, + ) + .map_err(|err| { + self.error = Err(err); + err + })?; // Warn unreachable subpatterns. for (arm, is_useful) in report.arm_usefulness.iter() { diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 1b4bcb789d2..a5c0b13c90b 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -1,4 +1,6 @@ -//! Analysis of patterns, notably match exhaustiveness checking. +//! Analysis of patterns, notably match exhaustiveness checking. The main entrypoint for this crate +//! is [`usefulness::compute_match_usefulness`]. For rustc-specific types and entrypoints, see the +//! [`rustc`] module. // tidy-alphabetical-start #![allow(rustc::diagnostic_outside_of_impl)] @@ -23,14 +25,8 @@ use std::fmt; pub use rustc_index::{Idx, IndexVec}; // re-exported to avoid rustc_index version issues -#[cfg(feature = "rustc")] -use rustc_middle::ty::Ty; -#[cfg(feature = "rustc")] -use rustc_span::ErrorGuaranteed; - use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::DeconstructedPat; -use crate::pat_column::PatternColumn; pub trait Captures<'a> {} impl<'a, T: ?Sized> Captures<'a> for T {} @@ -128,30 +124,3 @@ impl<'p, Cx: PatCx> Clone for MatchArm<'p, Cx> { } impl<'p, Cx: PatCx> Copy for MatchArm<'p, Cx> {} - -/// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are -/// useful, and runs some lints. -#[cfg(feature = "rustc")] -pub fn analyze_match<'p, 'tcx>( - tycx: &rustc::RustcPatCtxt<'p, 'tcx>, - arms: &[rustc::MatchArm<'p, 'tcx>], - scrut_ty: Ty<'tcx>, - pattern_complexity_limit: Option, -) -> Result, ErrorGuaranteed> { - use lints::lint_nonexhaustive_missing_variants; - use usefulness::{compute_match_usefulness, PlaceValidity}; - - let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); - let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee); - let report = - compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity, pattern_complexity_limit)?; - - // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting - // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. - if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() { - let pat_column = PatternColumn::new(arms); - lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?; - } - - Ok(report) -} diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 6ef2d69273e..dd815f7e0a1 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -20,6 +20,9 @@ use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; use crate::constructor::{ IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility, }; +use crate::lints::lint_nonexhaustive_missing_variants; +use crate::pat_column::PatternColumn; +use crate::usefulness::{compute_match_usefulness, PlaceValidity}; use crate::{errors, Captures, PatCx, PrivateUninhabitedField}; use crate::constructor::Constructor::*; @@ -1058,3 +1061,26 @@ fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { expand(pat, &mut pats); pats } + +/// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are +/// useful, and runs some lints. +pub fn analyze_match<'p, 'tcx>( + tycx: &RustcPatCtxt<'p, 'tcx>, + arms: &[MatchArm<'p, 'tcx>], + scrut_ty: Ty<'tcx>, + pattern_complexity_limit: Option, +) -> Result, ErrorGuaranteed> { + let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); + let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee); + let report = + compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity, pattern_complexity_limit)?; + + // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting + // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. + if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() { + let pat_column = PatternColumn::new(arms); + lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?; + } + + Ok(report) +} -- cgit 1.4.1-3-g733a5 From 64ac2b80822c33d69e6e61ea1eaf8a043bc35aad Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 21 Jul 2024 14:46:05 +0200 Subject: Explain why a given pattern is considered unreachable --- compiler/rustc_mir_build/messages.ftl | 5 +- compiler/rustc_mir_build/src/errors.rs | 32 ++- .../src/thir/pattern/check_match.rs | 64 ++++-- compiler/rustc_pattern_analysis/src/pat.rs | 17 +- compiler/rustc_pattern_analysis/src/rustc.rs | 2 + compiler/rustc_pattern_analysis/src/usefulness.rs | 193 +++++++++++++----- tests/ui/consts/packed_pattern.stderr | 4 +- tests/ui/consts/packed_pattern2.stderr | 4 +- tests/ui/error-codes/E0001.stderr | 6 +- .../exhaustiveness-unreachable-pattern.rs | 5 + .../exhaustiveness-unreachable-pattern.stderr | 226 +++++++++++++++------ tests/ui/pattern/usefulness/consts-opaque.stderr | 14 +- ...ty-match-check-notes.exhaustive_patterns.stderr | 17 +- .../empty-match-check-notes.normal.stderr | 17 +- .../pattern/usefulness/empty-match-check-notes.rs | 4 + .../empty-types.exhaustive_patterns.stderr | 87 +++++++- .../usefulness/empty-types.min_exh_pats.stderr | 87 +++++++- .../usefulness/empty-types.never_pats.stderr | 33 ++- .../pattern/usefulness/empty-types.normal.stderr | 33 ++- .../pattern/usefulness/explain-unreachable-pats.rs | 97 +++++++++ .../usefulness/explain-unreachable-pats.stderr | 92 +++++++++ tests/ui/pattern/usefulness/floats.stderr | 68 +++++-- tests/ui/pattern/usefulness/impl-trait.stderr | 27 ++- .../usefulness/integer-ranges/reachability.stderr | 119 ++++++++--- tests/ui/pattern/usefulness/issue-12116.stderr | 4 +- tests/ui/pattern/usefulness/issue-12369.stderr | 6 +- tests/ui/pattern/usefulness/issue-13727.stderr | 4 +- tests/ui/pattern/usefulness/issue-30240-b.stderr | 4 +- tests/ui/pattern/usefulness/issue-31221.stderr | 4 +- tests/ui/pattern/usefulness/issue-57472.stderr | 8 +- .../ui/pattern/usefulness/match-arm-statics.stderr | 18 +- .../usefulness/match-byte-array-patterns.stderr | 32 ++- tests/ui/pattern/usefulness/match-ref-ice.stderr | 4 +- tests/ui/pattern/usefulness/match-vec-fixed.stderr | 8 +- .../usefulness/match-vec-unreachable.stderr | 12 +- .../usefulness/slice-pattern-const-2.stderr | 17 +- .../usefulness/slice-pattern-const-3.stderr | 17 +- .../pattern/usefulness/slice-pattern-const.stderr | 39 +++- .../usefulness/slice-patterns-reachability.stderr | 27 ++- .../usefulness/top-level-alternation.stderr | 47 ++++- tests/ui/reachable/unreachable-arm.stderr | 4 +- .../ui/reachable/unreachable-loop-patterns.stderr | 1 + tests/ui/reachable/unreachable-try-pattern.stderr | 3 + .../unreachable.exh_pats.stderr | 11 + .../enum_same_crate_empty_match.stderr | 1 + .../issue-65157-repeated-match-arm.stderr | 4 +- .../uninhabited/patterns_same_crate.stderr | 9 + tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr | 4 +- tests/ui/uninhabited/uninhabited-patterns.stderr | 5 + 49 files changed, 1283 insertions(+), 263 deletions(-) create mode 100644 tests/ui/pattern/usefulness/explain-unreachable-pats.rs create mode 100644 tests/ui/pattern/usefulness/explain-unreachable-pats.stderr (limited to 'compiler/rustc_pattern_analysis/src') diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 281f3ef6ef3..8dd337f0c52 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -327,7 +327,10 @@ mir_build_union_pattern = cannot use unions in constant patterns mir_build_unreachable_pattern = unreachable pattern .label = unreachable pattern - .catchall_label = matches any value + .unreachable_matches_no_values = this pattern matches no values because `{$ty}` is uninhabited + .unreachable_covered_by_catchall = matches any value + .unreachable_covered_by_one = matches all the values already + .unreachable_covered_by_many = matches some of the same values mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index f6f443b64a6..cf2962d9fcf 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -582,11 +582,37 @@ pub(crate) struct NonConstPath { #[derive(LintDiagnostic)] #[diag(mir_build_unreachable_pattern)] -pub(crate) struct UnreachablePattern { +pub(crate) struct UnreachablePattern<'tcx> { #[label] pub(crate) span: Option, - #[label(mir_build_catchall_label)] - pub(crate) catchall: Option, + #[subdiagnostic] + pub(crate) matches_no_values: Option>, + #[label(mir_build_unreachable_covered_by_catchall)] + pub(crate) covered_by_catchall: Option, + #[label(mir_build_unreachable_covered_by_one)] + pub(crate) covered_by_one: Option, + #[subdiagnostic] + pub(crate) covered_by_many: Option, +} + +#[derive(Subdiagnostic)] +#[note(mir_build_unreachable_matches_no_values)] +pub(crate) struct UnreachableMatchesNoValues<'tcx> { + pub(crate) ty: Ty<'tcx>, +} + +pub(crate) struct UnreachableCoveredByMany(pub(crate) Vec); + +impl Subdiagnostic for UnreachableCoveredByMany { + fn add_to_diag_with>( + self, + diag: &mut Diag<'_, G>, + _f: &F, + ) { + for span in self.0 { + diag.span_label(span, fluent::mir_build_unreachable_covered_by_many); + } + } } #[derive(Diagnostic)] 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 28cb994b8e2..3c476a7766c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -16,8 +16,8 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_pattern_analysis::errors::Uncovered; use rustc_pattern_analysis::rustc::{ - Constructor, DeconstructedPat, MatchArm, RevealedTy, RustcPatCtxt as PatCtxt, Usefulness, - UsefulnessReport, WitnessPat, + Constructor, DeconstructedPat, MatchArm, RedundancyExplanation, RevealedTy, + RustcPatCtxt as PatCtxt, Usefulness, UsefulnessReport, WitnessPat, }; use rustc_session::lint::builtin::{ BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS, @@ -409,9 +409,9 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { { let mut redundant_subpats = redundant_subpats.clone(); // Emit lints in the order in which they occur in the file. - redundant_subpats.sort_unstable_by_key(|pat| pat.data().span); - for pat in redundant_subpats { - report_unreachable_pattern(cx, arm.arm_data, pat.data().span, None) + redundant_subpats.sort_unstable_by_key(|(pat, _)| pat.data().span); + for (pat, explanation) in redundant_subpats { + report_unreachable_pattern(cx, arm.arm_data, pat, &explanation) } } } @@ -910,26 +910,52 @@ fn report_irrefutable_let_patterns( fn report_unreachable_pattern<'p, 'tcx>( cx: &PatCtxt<'p, 'tcx>, hir_id: HirId, - span: Span, - catchall: Option, + pat: &DeconstructedPat<'p, 'tcx>, + explanation: &RedundancyExplanation<'p, 'tcx>, ) { - cx.tcx.emit_node_span_lint( - UNREACHABLE_PATTERNS, - hir_id, - span, - UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall }, - ); + let pat_span = pat.data().span; + let mut lint = UnreachablePattern { + span: Some(pat_span), + matches_no_values: None, + covered_by_catchall: None, + covered_by_one: None, + covered_by_many: None, + }; + match explanation.covered_by.as_slice() { + [] => { + // Empty pattern; we report the uninhabited type that caused the emptiness. + lint.span = None; // Don't label the pattern itself + pat.walk(&mut |subpat| { + let ty = **subpat.ty(); + if cx.is_uninhabited(ty) { + lint.matches_no_values = Some(UnreachableMatchesNoValues { ty }); + false // No need to dig further. + } else if matches!(subpat.ctor(), Constructor::Ref | Constructor::UnionField) { + false // Don't explore further since they are not by-value. + } else { + true + } + }); + } + [covering_pat] if pat_is_catchall(covering_pat) => { + lint.covered_by_catchall = Some(covering_pat.data().span); + } + [covering_pat] => { + lint.covered_by_one = Some(covering_pat.data().span); + } + covering_pats => { + let covering_spans = covering_pats.iter().map(|p| p.data().span).collect(); + lint.covered_by_many = Some(UnreachableCoveredByMany(covering_spans)); + } + } + cx.tcx.emit_node_span_lint(UNREACHABLE_PATTERNS, hir_id, pat_span, lint); } /// Report unreachable arms, if any. fn report_arm_reachability<'p, 'tcx>(cx: &PatCtxt<'p, 'tcx>, report: &UsefulnessReport<'p, 'tcx>) { - let mut catchall = None; for (arm, is_useful) in report.arm_usefulness.iter() { - if matches!(is_useful, Usefulness::Redundant) { - report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().span, catchall) - } - if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) { - catchall = Some(arm.pat.data().span); + if let Usefulness::Redundant(explanation) = is_useful { + report_unreachable_pattern(cx, arm.arm_data, arm.pat, explanation) } } } diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index e8d6c542c5f..a591c3c554b 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -11,7 +11,7 @@ use crate::{PatCx, PrivateUninhabitedField}; use self::Constructor::*; /// A globally unique id to distinguish patterns. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub(crate) struct PatId(u32); impl PatId { fn new() -> Self { @@ -147,6 +147,21 @@ impl fmt::Debug for DeconstructedPat { } } +/// Delegate to `uid`. +impl PartialEq for DeconstructedPat { + fn eq(&self, other: &Self) -> bool { + self.uid == other.uid + } +} +/// Delegate to `uid`. +impl Eq for DeconstructedPat {} +/// Delegate to `uid`. +impl std::hash::Hash for DeconstructedPat { + fn hash(&self, state: &mut H) { + self.uid.hash(state); + } +} + /// Represents either a pattern obtained from user input or a wildcard constructed during the /// algorithm. Do not use `Wild` to represent a wildcard pattern comping from user input. /// diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index dd815f7e0a1..910dd4c6c1a 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -32,6 +32,8 @@ pub type Constructor<'p, 'tcx> = crate::constructor::Constructor = crate::constructor::ConstructorSet>; pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcPatCtxt<'p, 'tcx>>; +pub type RedundancyExplanation<'p, 'tcx> = + crate::usefulness::RedundancyExplanation<'p, RustcPatCtxt<'p, 'tcx>>; pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcPatCtxt<'p, 'tcx>>; pub type UsefulnessReport<'p, 'tcx> = crate::usefulness::UsefulnessReport<'p, RustcPatCtxt<'p, 'tcx>>; diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 8486792b554..76dc338e71c 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -713,7 +713,7 @@ use self::PlaceValidity::*; use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat}; use crate::{Captures, MatchArm, PatCx, PrivateUninhabitedField}; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use rustc_index::bit_set::BitSet; use smallvec::{smallvec, SmallVec}; use std::fmt; @@ -726,18 +726,81 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { f() } +/// A pattern is a "branch" if it is the immediate child of an or-pattern, or if it is the whole +/// pattern of a match arm. These are the patterns that can be meaningfully considered "redundant", +/// since e.g. `0` in `(0, 1)` cannot be redundant on its own. +/// +/// We track for each branch pattern whether it is useful, and if not why. +struct BranchPatUsefulness<'p, Cx: PatCx> { + /// Whether this pattern is useful. + useful: bool, + /// A set of patterns that: + /// - come before this one in the match; + /// - intersect this one; + /// - at the end of the algorithm, if `!self.useful`, their union covers this pattern. + covered_by: FxHashSet<&'p DeconstructedPat>, +} + +impl<'p, Cx: PatCx> BranchPatUsefulness<'p, Cx> { + /// Update `self` with the usefulness information found in `row`. + fn update(&mut self, row: &MatrixRow<'p, Cx>, matrix: &Matrix<'p, Cx>) { + self.useful |= row.useful; + // This deserves an explanation: `intersects_at_least` does not contain all intersections + // because we skip irrelevant values (see the docs for `intersects_at_least` for an + // example). Yet we claim this suffices to build a covering set. + // + // Let `p` be our pattern. Assume it is found not useful. For a value `v`, if the value was + // relevant then we explored that value and found that there was another pattern `q` before + // `p` that matches it too. We therefore recorded an intersection with `q`. If `v` was + // irrelevant, we know there's another value `v2` that matches strictly fewer rows (while + // still matching our row) and is relevant. Since `p` is not useful, there must have been a + // `q` before `p` that matches `v2`, and we recorded that intersection. Since `v2` matches + // strictly fewer rows than `v`, `q` also matches `v`. In either case, we recorded in + // `intersects_at_least` a pattern that matches `v`. Hence using `intersects_at_least` is + // sufficient to build a covering set. + for row_id in row.intersects_at_least.iter() { + let row = &matrix.rows[row_id]; + if row.useful && !row.is_under_guard { + if let PatOrWild::Pat(intersecting) = row.head() { + self.covered_by.insert(intersecting); + } + } + } + } + + /// Check whether this pattern is redundant, and if so explain why. + fn is_redundant(&self) -> Option> { + if self.useful { + None + } else { + // We avoid instability by sorting by `uid`. The order of `uid`s only depends on the + // pattern structure. + #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))] + let mut covered_by: Vec<_> = self.covered_by.iter().copied().collect(); + covered_by.sort_by_key(|pat| pat.uid); // sort to avoid instability + Some(RedundancyExplanation { covered_by }) + } + } +} + +impl<'p, Cx: PatCx> Default for BranchPatUsefulness<'p, Cx> { + fn default() -> Self { + Self { useful: Default::default(), covered_by: Default::default() } + } +} + /// Context that provides information for usefulness checking. -struct UsefulnessCtxt<'a, Cx: PatCx> { +struct UsefulnessCtxt<'a, 'p, Cx: PatCx> { /// The context for type information. tycx: &'a Cx, - /// Collect the patterns found useful during usefulness checking. This is used to lint - /// unreachable (sub)patterns. - useful_subpatterns: FxHashSet, + /// Track information about the usefulness of branch patterns (see definition of "branch + /// pattern" at [`BranchPatUsefulness`]). + branch_usefulness: FxHashMap>, complexity_limit: Option, complexity_level: usize, } -impl<'a, Cx: PatCx> UsefulnessCtxt<'a, Cx> { +impl<'a, 'p, Cx: PatCx> UsefulnessCtxt<'a, 'p, Cx> { fn increase_complexity_level(&mut self, complexity_add: usize) -> Result<(), Cx::Error> { self.complexity_level += complexity_add; if self @@ -1051,14 +1114,40 @@ struct MatrixRow<'p, Cx: PatCx> { /// [`compute_exhaustiveness_and_usefulness`] if the arm is found to be useful. /// This is reset to `false` when specializing. useful: bool, - /// Tracks which rows above this one have an intersection with this one, i.e. such that there is - /// a value that matches both rows. - /// Note: Because of relevancy we may miss some intersections. The intersections we do find are - /// correct. - intersects: BitSet, + /// Tracks some rows above this one that have an intersection with this one, i.e. such that + /// there is a value that matches both rows. + /// Because of relevancy we may miss some intersections. The intersections we do find are + /// correct. In other words, this is an underapproximation of the real set of intersections. + /// + /// For example: + /// ```rust,ignore(illustrative) + /// match ... { + /// (true, _, _) => {} // `intersects_at_least = []` + /// (_, true, 0..=10) => {} // `intersects_at_least = []` + /// (_, true, 5..15) => {} // `intersects_at_least = [1]` + /// } + /// ``` + /// Here the `(true, true)` case is irrelevant. Since we skip it, we will not detect that row 0 + /// intersects rows 1 and 2. + intersects_at_least: BitSet, + /// Whether the head pattern is a branch (see definition of "branch pattern" at + /// [`BranchPatUsefulness`]) + head_is_branch: bool, } impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { + fn new(arm: &MatchArm<'p, Cx>, arm_id: usize) -> Self { + MatrixRow { + pats: PatStack::from_pattern(arm.pat), + parent_row: arm_id, + is_under_guard: arm.has_guard, + useful: false, + intersects_at_least: BitSet::new_empty(0), // Initialized in `Matrix::push`. + // This pattern is a branch because it comes from a match arm. + head_is_branch: true, + } + } + fn len(&self) -> usize { self.pats.len() } @@ -1076,12 +1165,14 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { &self, parent_row: usize, ) -> impl Iterator> + Captures<'_> { + let is_or_pat = self.pats.head().is_or_pat(); self.pats.expand_or_pat().map(move |patstack| MatrixRow { pats: patstack, parent_row, is_under_guard: self.is_under_guard, useful: false, - intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`. + intersects_at_least: BitSet::new_empty(0), // Initialized in `Matrix::push`. + head_is_branch: is_or_pat, }) } @@ -1100,7 +1191,8 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { parent_row, is_under_guard: self.is_under_guard, useful: false, - intersects: BitSet::new_empty(0), // Initialized in `Matrix::push`. + intersects_at_least: BitSet::new_empty(0), // Initialized in `Matrix::push`. + head_is_branch: false, }) } } @@ -1138,7 +1230,7 @@ struct Matrix<'p, Cx: PatCx> { impl<'p, Cx: PatCx> Matrix<'p, Cx> { /// Pushes a new row to the matrix. Internal method, prefer [`Matrix::new`]. fn push(&mut self, mut row: MatrixRow<'p, Cx>) { - row.intersects = BitSet::new_empty(self.rows.len()); + row.intersects_at_least = BitSet::new_empty(self.rows.len()); self.rows.push(row); } @@ -1156,14 +1248,7 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> { wildcard_row_is_relevant: true, }; for (arm_id, arm) in arms.iter().enumerate() { - let v = MatrixRow { - pats: PatStack::from_pattern(arm.pat), - parent_row: arm_id, - is_under_guard: arm.has_guard, - useful: false, - intersects: BitSet::new_empty(0), // Initialized in `Matrix::push`. - }; - matrix.push(v); + matrix.push(MatrixRow::new(arm, arm_id)); } matrix } @@ -1242,12 +1327,12 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> { let parent_row = &mut self.rows[parent_row_id]; // A parent row is useful if any of its children is. parent_row.useful |= child_row.useful; - for child_intersection in child_row.intersects.iter() { + for child_intersection in child_row.intersects_at_least.iter() { // Convert the intersecting ids into ids for the parent matrix. let parent_intersection = specialized.rows[child_intersection].parent_row; // Note: self-intersection can happen with or-patterns. if parent_intersection != parent_row_id { - parent_row.intersects.insert(parent_intersection); + parent_row.intersects_at_least.insert(parent_intersection); } } } @@ -1544,7 +1629,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: PatCx>( let overlaps_with: Vec<_> = prefixes .iter() .filter(|&&(other_child_row_id, _)| { - child_row.intersects.contains(other_child_row_id) + child_row.intersects_at_least.contains(other_child_row_id) }) .map(|&(_, pat)| pat) .collect(); @@ -1560,7 +1645,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: PatCx>( let overlaps_with: Vec<_> = suffixes .iter() .filter(|&&(other_child_row_id, _)| { - child_row.intersects.contains(other_child_row_id) + child_row.intersects_at_least.contains(other_child_row_id) }) .map(|&(_, pat)| pat) .collect(); @@ -1603,8 +1688,8 @@ fn collect_non_contiguous_range_endpoints<'p, Cx: PatCx>( /// The core of the algorithm. /// /// This recursively computes witnesses of the non-exhaustiveness of `matrix` (if any). Also tracks -/// usefulness of each row in the matrix (in `row.useful`). We track usefulness of each subpattern -/// in `mcx.useful_subpatterns`. +/// usefulness of each row in the matrix (in `row.useful`). We track usefulness of subpatterns in +/// `mcx.branch_usefulness`. /// /// The input `Matrix` and the output `WitnessMatrix` together match the type exhaustively. /// @@ -1616,7 +1701,7 @@ fn collect_non_contiguous_range_endpoints<'p, Cx: PatCx>( /// This is all explained at the top of the file. #[instrument(level = "debug", skip(mcx), ret)] fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( - mcx: &mut UsefulnessCtxt<'a, Cx>, + mcx: &mut UsefulnessCtxt<'a, 'p, Cx>, matrix: &mut Matrix<'p, Cx>, ) -> Result, Cx::Error> { debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); @@ -1635,7 +1720,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( let mut useful = true; // Whether the next row is useful. for (i, row) in matrix.rows_mut().enumerate() { row.useful = useful; - row.intersects.insert_range(0..i); + row.intersects_at_least.insert_range(0..i); // The next rows stays useful if this one is under a guard. useful &= row.is_under_guard; } @@ -1677,7 +1762,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( if let Constructor::IntRange(overlap_range) = ctor { if overlap_range.is_singleton() && spec_matrix.rows.len() >= 2 - && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty()) + && spec_matrix.rows.iter().any(|row| !row.intersects_at_least.is_empty()) { collect_overlapping_range_endpoints(mcx.tycx, overlap_range, matrix, &spec_matrix); } @@ -1697,14 +1782,11 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( } } - // Record usefulness in the patterns. + // Record usefulness of the branch patterns. for row in matrix.rows() { - if row.useful { + if row.head_is_branch { if let PatOrWild::Pat(pat) = row.head() { - let newly_useful = mcx.useful_subpatterns.insert(pat.uid); - if newly_useful { - debug!("newly useful: {pat:?}"); - } + mcx.branch_usefulness.entry(pat.uid).or_default().update(row, matrix); } } } @@ -1712,16 +1794,25 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( Ok(ret) } +/// Indicates why a given pattern is considered redundant. +#[derive(Clone, Debug)] +pub struct RedundancyExplanation<'p, Cx: PatCx> { + /// All the values matched by this pattern are already matched by the given set of patterns. + /// This list is not guaranteed to be minimal but the contained patterns are at least guaranteed + /// to intersect this pattern. + pub covered_by: Vec<&'p DeconstructedPat>, +} + /// Indicates whether or not a given arm is useful. #[derive(Clone, Debug)] pub enum Usefulness<'p, Cx: PatCx> { /// The arm is useful. This additionally carries a set of or-pattern branches that have been /// found to be redundant despite the overall arm being useful. Used only in the presence of /// or-patterns, otherwise it stays empty. - Useful(Vec<&'p DeconstructedPat>), + Useful(Vec<(&'p DeconstructedPat, RedundancyExplanation<'p, Cx>)>), /// The arm is redundant and can be removed without changing the behavior of the match /// expression. - Redundant, + Redundant(RedundancyExplanation<'p, Cx>), } /// The output of checking a match for exhaustiveness and arm usefulness. @@ -1747,7 +1838,7 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>( ) -> Result, Cx::Error> { let mut cx = UsefulnessCtxt { tycx, - useful_subpatterns: FxHashSet::default(), + branch_usefulness: FxHashMap::default(), complexity_limit, complexity_level: 0, }; @@ -1760,26 +1851,32 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>( .copied() .map(|arm| { debug!(?arm); - let usefulness = if cx.useful_subpatterns.contains(&arm.pat.uid) { + let usefulness = cx.branch_usefulness.get(&arm.pat.uid).unwrap(); + let usefulness = if let Some(explanation) = usefulness.is_redundant() { + Usefulness::Redundant(explanation) + } else { let mut redundant_subpats = Vec::new(); arm.pat.walk(&mut |subpat| { - if cx.useful_subpatterns.contains(&subpat.uid) { - true // keep recursing + if let Some(u) = cx.branch_usefulness.get(&subpat.uid) { + if let Some(explanation) = u.is_redundant() { + redundant_subpats.push((subpat, explanation)); + false // stop recursing + } else { + true // keep recursing + } } else { - redundant_subpats.push(subpat); - false // stop recursing + true // keep recursing } }); Usefulness::Useful(redundant_subpats) - } else { - Usefulness::Redundant }; debug!(?usefulness); (arm, usefulness) }) .collect(); - let arm_intersections: Vec<_> = matrix.rows().map(|row| row.intersects.clone()).collect(); + let arm_intersections: Vec<_> = + matrix.rows().map(|row| row.intersects_at_least.clone()).collect(); Ok(UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses, arm_intersections }) } diff --git a/tests/ui/consts/packed_pattern.stderr b/tests/ui/consts/packed_pattern.stderr index 9ca50a95e4e..a0b434b2d78 100644 --- a/tests/ui/consts/packed_pattern.stderr +++ b/tests/ui/consts/packed_pattern.stderr @@ -1,8 +1,10 @@ warning: unreachable pattern --> $DIR/packed_pattern.rs:16:9 | +LL | Foo { field: (5, 6, 7, 8) } => {}, + | --------------------------- matches all the values already LL | FOO => unreachable!(), - | ^^^ + | ^^^ unreachable pattern | = note: `#[warn(unreachable_patterns)]` on by default diff --git a/tests/ui/consts/packed_pattern2.stderr b/tests/ui/consts/packed_pattern2.stderr index 4dc54461eeb..4785f4d0297 100644 --- a/tests/ui/consts/packed_pattern2.stderr +++ b/tests/ui/consts/packed_pattern2.stderr @@ -1,8 +1,10 @@ warning: unreachable pattern --> $DIR/packed_pattern2.rs:24:9 | +LL | Bar { a: Foo { field: (5, 6) } } => {}, + | -------------------------------- matches all the values already LL | FOO => unreachable!(), - | ^^^ + | ^^^ unreachable pattern | = note: `#[warn(unreachable_patterns)]` on by default diff --git a/tests/ui/error-codes/E0001.stderr b/tests/ui/error-codes/E0001.stderr index 49bb73e7ba8..bf8c5235f70 100644 --- a/tests/ui/error-codes/E0001.stderr +++ b/tests/ui/error-codes/E0001.stderr @@ -1,8 +1,12 @@ error: unreachable pattern --> $DIR/E0001.rs:8:9 | +LL | Some(_) => {/* ... */} + | ------- matches some of the same values +LL | None => {/* ... */} + | ---- matches some of the same values LL | _ => {/* ... */} - | ^ + | ^ unreachable pattern | note: the lint level is defined here --> $DIR/E0001.rs:1:9 diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs index 1ad335bf394..afdcff0346b 100644 --- a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs @@ -29,6 +29,11 @@ fn main() { (1, 4 | 5) => {} //~ ERROR unreachable pattern _ => {} } + match (0u8, 0u8, 0u8) { + (0, 0, 0) => {} + (0, 0 | 1, 0) => {} //~ ERROR unreachable pattern + _ => {} + } match (true, true) { (false | true, false | true) => (), } diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr index 336530d1b32..5c7d9db1c92 100644 --- a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:8:9 | +LL | (1 | 2,) => {} + | -------- matches all the values already LL | (1,) => {} - | ^^^^ + | ^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/exhaustiveness-unreachable-pattern.rs:1:9 @@ -13,212 +15,310 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:13:9 | +LL | (1 | 2,) => {} + | -------- matches all the values already LL | (2,) => {} - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:19:9 | +LL | (1,) => {} + | ---- matches some of the same values +LL | (2,) => {} + | ---- matches some of the same values LL | (1 | 2,) => {} - | ^^^^^^^^ + | ^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:24:9 | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches all the values already LL | (1, 3) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:25:9 | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches all the values already +LL | (1, 3) => {} LL | (1, 4) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:26:9 | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches all the values already +... LL | (2, 4) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:27:9 | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches all the values already +... LL | (2 | 1, 4) => {} - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:29:9 | +LL | (1 | 2, 3 | 4) => {} + | -------------- matches some of the same values +... +LL | (1, 5 | 6) => {} + | ---------- matches some of the same values LL | (1, 4 | 5) => {} - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:37:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:34:13 | +LL | (0, 0, 0) => {} + | - matches all the values already +LL | (0, 0 | 1, 0) => {} + | ^ unreachable pattern + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:42:9 + | +LL | (None | Some(1 | 2),) => {} + | --------------------- matches all the values already LL | (Some(1),) => {} - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:38:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9 | +LL | (None | Some(1 | 2),) => {} + | --------------------- matches all the values already +LL | (Some(1),) => {} LL | (None,) => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:48:9 | +LL | ((1 | 2,) | (3 | 4,),) => {} + | ---------------------- matches all the values already LL | ((1..=4,),) => {} - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:48:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:53:14 | LL | (1 | 1,) => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:52:19 + --> $DIR/exhaustiveness-unreachable-pattern.rs:57:19 | LL | (0 | 1) | 1 => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:58:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:63:14 | LL | 0 | (0 | 0) => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:58:18 + --> $DIR/exhaustiveness-unreachable-pattern.rs:63:18 | LL | 0 | (0 | 0) => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:66:13 + --> $DIR/exhaustiveness-unreachable-pattern.rs:71:13 | +LL | Some(0) | + | ------- matches all the values already LL | / Some( LL | | 0 | 0) => {} - | |______________________^ + | |______________________^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:72:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:77:15 | +LL | [0 + | - matches all the values already LL | | 0 - | ^ + | ^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:74:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:79:15 | +LL | , 0 + | - matches all the values already LL | | 0] => {} - | ^ + | ^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:78:20 + --> $DIR/exhaustiveness-unreachable-pattern.rs:83:20 | LL | (true, 0 | 0) => {} - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:79:17 + --> $DIR/exhaustiveness-unreachable-pattern.rs:84:17 | +LL | (true, 0 | 0) => {} + | - matches some of the same values LL | (_, 0 | 0) => {} - | ^ + | - ^ unreachable pattern + | | + | matches some of the same values error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:87:10 + --> $DIR/exhaustiveness-unreachable-pattern.rs:92:10 | +LL | [1, ..] => {} + | - matches all the values already LL | [1 - | ^ + | ^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:99:10 + --> $DIR/exhaustiveness-unreachable-pattern.rs:104:10 | +LL | [true, ..] => {} + | ---- matches all the values already LL | [true - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:106:36 + --> $DIR/exhaustiveness-unreachable-pattern.rs:111:36 | +LL | (true, Some(_)) => {} + | - matches some of the same values +LL | (false, Some(true)) => {} + | ---- matches some of the same values LL | (true | false, None | Some(true - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:111:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14 | LL | (true - | ^^^^ + | ^^^^ unreachable pattern ... +LL | (true, Some(_)) => {} + | - matches some of the same values +LL | (false, Some(true)) => {} + | ---- matches some of the same values LL | (true | false, None | Some(t_or_f!())) => {} | --------- in this macro invocation | = note: this error originates in the macro `t_or_f` (in Nightly builds, run with -Z macro-backtrace for more info) error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:122:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:127:14 | +LL | Some(0) => {} + | - matches all the values already LL | Some(0 - | ^ + | ^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:141:19 + --> $DIR/exhaustiveness-unreachable-pattern.rs:146:19 | +LL | Some(false) => {} + | ----- matches all the values already +LL | None | Some(true LL | | false) => {} - | ^^^^^ + | ^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:149:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:154:15 | +LL | (false, true) => {} + | ---- matches some of the same values +LL | (true, true) => {} + | ---- matches some of the same values +LL | (false | true, false LL | | true) => {} - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:155:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15 | +LL | (true, false) => {} + | ---- matches some of the same values +LL | (true, true) => {} + | ---- matches some of the same values +LL | (false LL | | true, - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:165:15 | +LL | (x, y) + | ------ matches any value LL | | (y, x) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:164:30 + --> $DIR/exhaustiveness-unreachable-pattern.rs:169:30 | LL | fn unreachable_in_param((_ | (_, _)): (bool, bool)) {} - | ^^^^^^ + | - ^^^^^^ unreachable pattern + | | + | matches any value error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:171:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:176:14 | LL | let (_ | (_, _)) = bool_pair; - | ^^^^^^ + | - ^^^^^^ unreachable pattern + | | + | matches any value error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:173:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:178:14 | LL | for (_ | (_, _)) in [bool_pair] {} - | ^^^^^^ + | - ^^^^^^ unreachable pattern + | | + | matches any value error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:176:20 + --> $DIR/exhaustiveness-unreachable-pattern.rs:181:20 | LL | let (Some(_) | Some(true)) = bool_option else { return }; - | ^^^^^^^^^^ + | ------- ^^^^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:178:22 + --> $DIR/exhaustiveness-unreachable-pattern.rs:183:22 | LL | if let Some(_) | Some(true) = bool_option {} - | ^^^^^^^^^^ + | ------- ^^^^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:180:25 + --> $DIR/exhaustiveness-unreachable-pattern.rs:185:25 | LL | while let Some(_) | Some(true) = bool_option {} - | ^^^^^^^^^^ + | ------- ^^^^^^^^^^ unreachable pattern + | | + | matches all the values already -error: aborting due to 35 previous errors +error: aborting due to 36 previous errors diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index d057309e420..fdec3683c4a 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -106,20 +106,28 @@ LL | _ => {} // should not be emitting unreachable warning error: unreachable pattern --> $DIR/consts-opaque.rs:72:9 | +LL | BAZ => {} + | --- matches all the values already LL | Baz::Baz1 => {} // should not be emitting unreachable warning - | ^^^^^^^^^ + | ^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:79:9 | +LL | Baz::Baz1 => {} + | --------- matches all the values already LL | BAZ => {} - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:87:9 | +LL | BAZ => {} + | --- matches some of the same values +LL | Baz::Baz2 => {} + | --------- matches some of the same values LL | _ => {} // should not be emitting unreachable warning - | ^ + | ^ unreachable pattern error: aborting due to 17 previous errors diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr index 4c434192431..9e700ee55ef 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `EmptyEnum` is uninhabited note: the lint level is defined here --> $DIR/empty-match-check-notes.rs:7:9 | @@ -11,25 +12,31 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:20:9 + --> $DIR/empty-match-check-notes.rs:21:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `EmptyEnum` is uninhabited error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:27:9 + --> $DIR/empty-match-check-notes.rs:29:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:30:9 + --> $DIR/empty-match-check-notes.rs:33:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited error[E0005]: refutable pattern in local binding - --> $DIR/empty-match-check-notes.rs:35:9 + --> $DIR/empty-match-check-notes.rs:39:9 | LL | let None = x; | ^^^^ pattern `Some(_)` not covered @@ -44,7 +51,7 @@ LL | if let None = x { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered - --> $DIR/empty-match-check-notes.rs:45:11 + --> $DIR/empty-match-check-notes.rs:49:11 | LL | match 0u8 { | ^^^ pattern `0_u8..=u8::MAX` not covered diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr index 45f715dc7b2..480ae7095a6 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `EmptyEnum` is uninhabited note: the lint level is defined here --> $DIR/empty-match-check-notes.rs:7:9 | @@ -11,25 +12,31 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:20:9 + --> $DIR/empty-match-check-notes.rs:21:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `EmptyEnum` is uninhabited error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:27:9 + --> $DIR/empty-match-check-notes.rs:29:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited error: unreachable pattern - --> $DIR/empty-match-check-notes.rs:30:9 + --> $DIR/empty-match-check-notes.rs:33:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `EmptyForeignEnum` is uninhabited error[E0005]: refutable pattern in local binding - --> $DIR/empty-match-check-notes.rs:35:9 + --> $DIR/empty-match-check-notes.rs:39:9 | LL | let None = x; | ^^^^ pattern `Some(_)` not covered @@ -43,7 +50,7 @@ LL | if let None = x { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered - --> $DIR/empty-match-check-notes.rs:45:11 + --> $DIR/empty-match-check-notes.rs:49:11 | LL | match 0u8 { | ^^^ pattern `0_u8..=u8::MAX` not covered diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs index ea797bc7dd5..2eef283a21e 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.rs +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs @@ -15,9 +15,11 @@ fn empty_enum(x: EmptyEnum) { match x {} // ok match x { _ => {} //~ ERROR unreachable pattern + //~^ NOTE matches no values } match x { _ if false => {} //~ ERROR unreachable pattern + //~^ NOTE matches no values } } @@ -25,9 +27,11 @@ fn empty_foreign_enum(x: empty::EmptyForeignEnum) { match x {} // ok match x { _ => {} //~ ERROR unreachable pattern + //~^ NOTE matches no values } match x { _ if false => {} //~ ERROR unreachable pattern + //~^ NOTE matches no values } } diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr index 45bdba94d78..416a50b87b5 100644 --- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/empty-types.rs:17:9 | @@ -15,6 +16,8 @@ error: unreachable pattern | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:58:11 @@ -36,24 +39,32 @@ error: unreachable pattern | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(u32, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:80:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:87:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(_)` not covered --> $DIR/empty-types.rs:91:11 @@ -79,12 +90,16 @@ error: unreachable pattern | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:104:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered --> $DIR/empty-types.rs:101:11 @@ -123,114 +138,152 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:123:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:126:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:127:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:130:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:131:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:140:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:152:13 | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:156:13 | +LL | None => {} + | ---- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/empty-types.rs:208:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:218:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:223:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:229:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:288:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:291:9 | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:294:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:295:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty --> $DIR/empty-types.rs:327:11 @@ -292,18 +345,24 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:372:9 | LL | [_, _, _] => {} | ^^^^^^^^^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:375:9 | LL | [_, ..] => {} | ^^^^^^^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty --> $DIR/empty-types.rs:389:11 @@ -322,8 +381,10 @@ LL + } error: unreachable pattern --> $DIR/empty-types.rs:396:9 | +LL | [] => {} + | -- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `[]` not covered --> $DIR/empty-types.rs:398:11 @@ -344,48 +405,66 @@ error: unreachable pattern | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:422:9 | LL | Some(_a) => {} | ^^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:427:9 | +LL | None => {} + | ---- matches all the values already +LL | // !useful, !reachable LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/empty-types.rs:432:9 | +LL | None => {} + | ---- matches all the values already +LL | // !useful, !reachable LL | _a => {} - | ^^ + | ^^ unreachable pattern error: unreachable pattern --> $DIR/empty-types.rs:604:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:607:9 | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:610:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:613:9 | LL | _x if false => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: aborting due to 49 previous errors diff --git a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr index 9b57c895eea..2e5511527d5 100644 --- a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/empty-types.rs:17:9 | @@ -15,6 +16,8 @@ error: unreachable pattern | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:58:11 @@ -36,24 +39,32 @@ error: unreachable pattern | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(u32, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:80:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:87:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(_)` not covered --> $DIR/empty-types.rs:91:11 @@ -79,12 +90,16 @@ error: unreachable pattern | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:104:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered --> $DIR/empty-types.rs:101:11 @@ -137,60 +152,80 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:123:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:126:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:127:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:130:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:131:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:140:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:152:13 | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:156:13 | +LL | None => {} + | ---- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/empty-types.rs:165:15 @@ -216,54 +251,72 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:218:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:223:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:229:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:288:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:291:9 | LL | (_, _) => {} | ^^^^^^ + | + = note: this pattern matches no values because `(!, !)` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:294:9 | LL | Ok(_) => {} | ^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:295:9 | LL | Err(_) => {} | ^^^^^^ + | + = note: this pattern matches no values because `Result` is uninhabited error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty --> $DIR/empty-types.rs:316:11 @@ -403,18 +456,24 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:372:9 | LL | [_, _, _] => {} | ^^^^^^^^^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:375:9 | LL | [_, ..] => {} | ^^^^^^^ + | + = note: this pattern matches no values because `[!; 3]` is uninhabited error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty --> $DIR/empty-types.rs:389:11 @@ -433,8 +492,10 @@ LL + } error: unreachable pattern --> $DIR/empty-types.rs:396:9 | +LL | [] => {} + | -- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `[]` not covered --> $DIR/empty-types.rs:398:11 @@ -455,24 +516,34 @@ error: unreachable pattern | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:422:9 | LL | Some(_a) => {} | ^^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:427:9 | +LL | None => {} + | ---- matches all the values already +LL | // !useful, !reachable LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/empty-types.rs:432:9 | +LL | None => {} + | ---- matches all the values already +LL | // !useful, !reachable LL | _a => {} - | ^^ + | ^^ unreachable pattern error[E0004]: non-exhaustive patterns: `&Some(_)` not covered --> $DIR/empty-types.rs:452:11 @@ -569,24 +640,32 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:607:9 | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:610:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:613:9 | LL | _x if false => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `&_` not covered --> $DIR/empty-types.rs:638:11 diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr index 0ff2472922e..4856a2f8e08 100644 --- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr @@ -13,6 +13,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/empty-types.rs:17:9 | @@ -24,6 +25,8 @@ error: unreachable pattern | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:58:11 @@ -73,6 +76,8 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(!)` not covered --> $DIR/empty-types.rs:91:11 @@ -218,12 +223,16 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error[E0004]: non-exhaustive patterns: `Some(!)` not covered --> $DIR/empty-types.rs:146:15 @@ -266,36 +275,48 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:218:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:223:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:229:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:288:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty --> $DIR/empty-types.rs:316:11 @@ -460,8 +481,10 @@ LL + } error: unreachable pattern --> $DIR/empty-types.rs:396:9 | +LL | [] => {} + | -- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `[]` not covered --> $DIR/empty-types.rs:398:11 @@ -568,24 +591,32 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:607:9 | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:610:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:613:9 | LL | _x if false => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `&!` not covered --> $DIR/empty-types.rs:638:11 diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index 1d13802a2bd..78db9ee349b 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/empty-types.rs:17:9 | @@ -15,6 +16,8 @@ error: unreachable pattern | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/empty-types.rs:58:11 @@ -64,6 +67,8 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered --> $DIR/empty-types.rs:91:11 @@ -209,12 +214,16 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/empty-types.rs:146:15 @@ -257,36 +266,48 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:218:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:223:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:229:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:288:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty --> $DIR/empty-types.rs:316:11 @@ -451,8 +472,10 @@ LL + } error: unreachable pattern --> $DIR/empty-types.rs:396:9 | +LL | [] => {} + | -- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error[E0004]: non-exhaustive patterns: `[]` not covered --> $DIR/empty-types.rs:398:11 @@ -559,24 +582,32 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:607:9 | LL | _x => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:610:9 | LL | _ if false => {} | ^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/empty-types.rs:613:9 | LL | _x if false => {} | ^^ + | + = note: this pattern matches no values because `!` is uninhabited error[E0004]: non-exhaustive patterns: `&_` not covered --> $DIR/empty-types.rs:638:11 diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs new file mode 100644 index 00000000000..6a27f7d4a82 --- /dev/null +++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs @@ -0,0 +1,97 @@ +#![feature(never_type)] +#![feature(min_exhaustive_patterns)] +#![deny(unreachable_patterns)] +//~^ NOTE lint level is defined here + +#[rustfmt::skip] +fn main() { + match (0u8,) { + (1 | 2,) => {} + //~^ NOTE matches all the values already + (2,) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + _ => {} + } + + match (0u8,) { + (1,) => {} + //~^ NOTE matches some of the same values + (2,) => {} + //~^ NOTE matches some of the same values + (1 | 2,) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + _ => {} + } + + let res: Result<(),!> = Ok(()); + match res { + Ok(_) => {} + Err(_) => {} + //~^ ERROR unreachable pattern + //~| NOTE this pattern matches no values because `!` is uninhabited + } + + #[derive(Copy, Clone)] + enum Void1 {} + #[derive(Copy, Clone)] + enum Void2 {} + // Only an empty type matched _by value_ can make an arm unreachable. We must get the right one. + let res1: Result<(), Void1> = Ok(()); + let res2: Result<(), Void2> = Ok(()); + match (&res1, res2) { + (Err(_), Err(_)) => {} + //~^ ERROR unreachable pattern + //~| NOTE this pattern matches no values because `Void2` is uninhabited + _ => {} + } + match (res1, &res2) { + (Err(_), Err(_)) => {} + //~^ ERROR unreachable pattern + //~| NOTE this pattern matches no values because `Void1` is uninhabited + _ => {} + } + + + if let (0 + //~^ NOTE matches all the values already + | 0, _) = (0, 0) {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + + match (true, true) { + (_, true) if false => {} // Guarded patterns don't cover others + (true, _) => {} + //~^ NOTE matches some of the same values + (false, _) => {} + //~^ NOTE matches some of the same values + (_, true) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + } + + match (true, true) { + (true, _) => {} + //~^ NOTE matches all the values already + (false, _) => {} + #[allow(unreachable_patterns)] + (_, true) => {} // Doesn't cover below because it's already unreachable. + (true, true) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + } + + // Despite skipping some irrelevant cases, we still report a set of rows that covers the + // unreachable one. + match (true, true, 0) { + (true, _, _) => {} + (_, true, 0..10) => {} + //~^ NOTE matches all the values already + (_, true, 10..) => {} + (_, true, 3) => {} + //~^ ERROR unreachable pattern + //~| NOTE unreachable pattern + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr new file mode 100644 index 00000000000..7c2382c26b8 --- /dev/null +++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr @@ -0,0 +1,92 @@ +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:11:9 + | +LL | (1 | 2,) => {} + | -------- matches all the values already +LL | +LL | (2,) => {} + | ^^^^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/explain-unreachable-pats.rs:3:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:22:9 + | +LL | (1,) => {} + | ---- matches some of the same values +LL | +LL | (2,) => {} + | ---- matches some of the same values +LL | +LL | (1 | 2,) => {} + | ^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:31:9 + | +LL | Err(_) => {} + | ^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:44:9 + | +LL | (Err(_), Err(_)) => {} + | ^^^^^^^^^^^^^^^^ + | + = note: this pattern matches no values because `Void2` is uninhabited + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:50:9 + | +LL | (Err(_), Err(_)) => {} + | ^^^^^^^^^^^^^^^^ + | + = note: this pattern matches no values because `Void1` is uninhabited + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:59:11 + | +LL | if let (0 + | - matches all the values already +LL | +LL | | 0, _) = (0, 0) {} + | ^ unreachable pattern + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:69:9 + | +LL | (true, _) => {} + | --------- matches some of the same values +LL | +LL | (false, _) => {} + | ---------- matches some of the same values +LL | +LL | (_, true) => {} + | ^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:80:9 + | +LL | (true, _) => {} + | --------- matches all the values already +... +LL | (true, true) => {} + | ^^^^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/explain-unreachable-pats.rs:92:9 + | +LL | (_, true, 0..10) => {} + | ---------------- matches all the values already +... +LL | (_, true, 3) => {} + | ^^^^^^^^^^^^ unreachable pattern + +error: aborting due to 9 previous errors + diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr index 684f6c93a16..d0a8841d6a8 100644 --- a/tests/ui/pattern/usefulness/floats.stderr +++ b/tests/ui/pattern/usefulness/floats.stderr @@ -14,8 +14,10 @@ LL + _ => todo!() error: unreachable pattern --> $DIR/floats.rs:18:9 | +LL | 0.01f16..=6.5f16 => {} + | ---------------- matches all the values already LL | 0.01f16 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/floats.rs:1:9 @@ -26,80 +28,118 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/floats.rs:19:9 | +LL | 0.01f16..=6.5f16 => {} + | ---------------- matches all the values already +LL | 0.01f16 => {} LL | 0.02f16 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:20:9 | +LL | 0.01f16..=6.5f16 => {} + | ---------------- matches all the values already +... LL | 6.5f16 => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:31:9 | +LL | 0.01f32..=6.5f32 => {} + | ---------------- matches all the values already LL | 0.01f32 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:32:9 | +LL | 0.01f32..=6.5f32 => {} + | ---------------- matches all the values already +LL | 0.01f32 => {} LL | 0.02f32 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:33:9 | +LL | 0.01f32..=6.5f32 => {} + | ---------------- matches all the values already +... LL | 6.5f32 => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:45:9 | +LL | 0.01f64..=6.5f64 => {} + | ---------------- matches all the values already +LL | 0.005f64 => {} LL | 0.01f64 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:46:9 | +LL | 0.01f64..=6.5f64 => {} + | ---------------- matches all the values already +... LL | 0.02f64 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:47:9 | +LL | 0.01f64..=6.5f64 => {} + | ---------------- matches all the values already +... LL | 6.5f64 => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:49:9 | +LL | 0.01f64..=6.5f64 => {} + | ---------------- matches all the values already +... LL | 1.0f64..=4.0f64 => {} - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:62:9 | +LL | 0.01f128..=6.5f128 => {} + | ------------------ matches all the values already +LL | 0.005f128 => {} LL | 0.01f128 => {} - | ^^^^^^^^ + | ^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:63:9 | +LL | 0.01f128..=6.5f128 => {} + | ------------------ matches all the values already +... LL | 0.02f128 => {} - | ^^^^^^^^ + | ^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:64:9 | +LL | 0.01f128..=6.5f128 => {} + | ------------------ matches all the values already +... LL | 6.5f128 => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/floats.rs:66:9 | +LL | 0.01f128..=6.5f128 => {} + | ------------------ matches all the values already +... LL | 1.0f128..=4.0f128 => {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ unreachable pattern error: aborting due to 15 previous errors diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr index ba8b12f9f66..c079f5a259d 100644 --- a/tests/ui/pattern/usefulness/impl-trait.stderr +++ b/tests/ui/pattern/usefulness/impl-trait.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `Void` is uninhabited note: the lint level is defined here --> $DIR/impl-trait.rs:5:9 | @@ -15,36 +16,48 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:45:13 | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:49:13 | +LL | None => {} + | ---- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/impl-trait.rs:59:13 | LL | Some(_) => {} | ^^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:63:13 | +LL | None => {} + | ---- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/impl-trait.rs:76:9 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:86:9 @@ -59,12 +72,16 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:105:9 | +LL | Some((a, b)) => {} + | ------------ matches all the values already LL | Some((mut x, mut y)) => { - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/impl-trait.rs:124:13 @@ -79,12 +96,16 @@ error: unreachable pattern | LL | _ => {} | ^ + | + = note: this pattern matches no values because `SecretelyVoid` is uninhabited error: unreachable pattern --> $DIR/impl-trait.rs:151:13 | LL | _ => {} | ^ + | + = note: this pattern matches no values because `SecretelyDoubleVoid` is uninhabited error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty --> $DIR/impl-trait.rs:23:11 diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr index c5b028d2038..8cf81822659 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/reachability.rs:18:17 | LL | m!(0u8, 42, 42); - | ^^ + | -- ^^ unreachable pattern + | | + | matches all the values already | note: the lint level is defined here --> $DIR/reachability.rs:3:9 @@ -14,121 +16,181 @@ error: unreachable pattern --> $DIR/reachability.rs:22:22 | LL | m!(0u8, 20..=30, 20); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:23:22 | LL | m!(0u8, 20..=30, 21); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:24:22 | LL | m!(0u8, 20..=30, 25); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:25:22 | LL | m!(0u8, 20..=30, 29); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:26:22 | LL | m!(0u8, 20..=30, 30); - | ^^ + | ------- ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:29:21 | LL | m!(0u8, 20..30, 20); - | ^^ + | ------ ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:30:21 | LL | m!(0u8, 20..30, 21); - | ^^ + | ------ ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:31:21 | LL | m!(0u8, 20..30, 25); - | ^^ + | ------ ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:32:21 | LL | m!(0u8, 20..30, 29); - | ^^ + | ------ ^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:36:22 | LL | m!(0u8, 20..=30, 20..=30); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:37:22 | LL | m!(0u8, 20.. 30, 20.. 30); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:38:22 | LL | m!(0u8, 20..=30, 20.. 30); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:40:22 | LL | m!(0u8, 20..=30, 21..=30); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:41:22 | LL | m!(0u8, 20..=30, 20..=29); - | ^^^^^^^ + | ------- ^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:43:24 | LL | m!('a', 'A'..='z', 'a'..='z'); - | ^^^^^^^^^ + | --------- ^^^^^^^^^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/reachability.rs:50:9 | +LL | 5 => {}, + | - matches some of the same values +LL | 6 => {}, + | - matches some of the same values +LL | 7 => {}, + | - matches some of the same values +LL | 8 => {}, + | - matches some of the same values LL | 5..=8 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern error: unreachable pattern --> $DIR/reachability.rs:56:9 | +LL | 0..10 => {}, + | ----- matches some of the same values +LL | 10..20 => {}, + | ------ matches some of the same values LL | 5..15 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern error: unreachable pattern --> $DIR/reachability.rs:63:9 | +LL | 0..10 => {}, + | ----- matches some of the same values +LL | 10..20 => {}, + | ------ matches some of the same values +LL | 20..30 => {}, + | ------ matches some of the same values LL | 5..25 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern error: unreachable pattern --> $DIR/reachability.rs:71:9 | +LL | 0..10 => {}, + | ----- matches some of the same values +LL | 10 => {}, + | -- matches some of the same values +LL | 11..=23 => {}, + | ------- matches some of the same values +LL | 19..30 => {}, + | ------ matches some of the same values LL | 5..25 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern error: unreachable pattern --> $DIR/reachability.rs:77:9 | +LL | 0..10 => {}, + | ----- matches some of the same values +LL | 10..20 => {}, + | ------ matches some of the same values LL | 5..15 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern error: unreachable pattern --> $DIR/reachability.rs:84:9 @@ -141,20 +203,29 @@ LL | '\u{D7FF}'..='\u{E000}' => {}, error: unreachable pattern --> $DIR/reachability.rs:89:9 | +LL | '\u{0}'..='\u{D7FF}' => {}, + | -------------------- matches some of the same values +LL | '\u{E000}'..='\u{10_FFFF}' => {}, + | -------------------------- matches some of the same values LL | '\u{D7FF}'..='\u{E000}' => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/reachability.rs:105:9 | +LL | &42 => {} + | --- matches all the values already LL | &FOO => {} - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern --> $DIR/reachability.rs:106:9 | +LL | &42 => {} + | --- matches all the values already +LL | &FOO => {} LL | BAR => {} - | ^^^ + | ^^^ unreachable pattern error: aborting due to 25 previous errors diff --git a/tests/ui/pattern/usefulness/issue-12116.stderr b/tests/ui/pattern/usefulness/issue-12116.stderr index 199bdc6ac97..b2c2be97563 100644 --- a/tests/ui/pattern/usefulness/issue-12116.stderr +++ b/tests/ui/pattern/usefulness/issue-12116.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/issue-12116.rs:15:9 | +LL | &IntList::Cons(val, box ref next_list) => tail(next_list), + | -------------------------------------- matches all the values already LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-12116.rs:4:9 diff --git a/tests/ui/pattern/usefulness/issue-12369.stderr b/tests/ui/pattern/usefulness/issue-12369.stderr index 2b6e2e14b7c..dbd6bab6aeb 100644 --- a/tests/ui/pattern/usefulness/issue-12369.stderr +++ b/tests/ui/pattern/usefulness/issue-12369.stderr @@ -1,8 +1,12 @@ error: unreachable pattern --> $DIR/issue-12369.rs:9:9 | +LL | &[a,b,c] => 3, + | -------- matches some of the same values +LL | &[a, ref rest @ ..] => a, + | ------------------- matches some of the same values LL | &[10,a, ref rest @ ..] => 10 - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-12369.rs:1:9 diff --git a/tests/ui/pattern/usefulness/issue-13727.stderr b/tests/ui/pattern/usefulness/issue-13727.stderr index ab80c56ea88..ca8533b33a4 100644 --- a/tests/ui/pattern/usefulness/issue-13727.stderr +++ b/tests/ui/pattern/usefulness/issue-13727.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/issue-13727.rs:7:5 | +LL | 256 => print!("0b1110\n"), + | --- matches all the values already LL | 512 => print!("0b1111\n"), - | ^^^ + | ^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-13727.rs:2:9 diff --git a/tests/ui/pattern/usefulness/issue-30240-b.stderr b/tests/ui/pattern/usefulness/issue-30240-b.stderr index 74d39eba98c..749515fc94b 100644 --- a/tests/ui/pattern/usefulness/issue-30240-b.stderr +++ b/tests/ui/pattern/usefulness/issue-30240-b.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/issue-30240-b.rs:12:9 | LL | "hello" => {} - | ^^^^^^^ + | ------- matches all the values already +LL | "hello" => {} + | ^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-30240-b.rs:1:9 diff --git a/tests/ui/pattern/usefulness/issue-31221.stderr b/tests/ui/pattern/usefulness/issue-31221.stderr index 7d349144456..f564422faae 100644 --- a/tests/ui/pattern/usefulness/issue-31221.stderr +++ b/tests/ui/pattern/usefulness/issue-31221.stderr @@ -23,8 +23,10 @@ LL | &Var2 => (), error: unreachable pattern --> $DIR/issue-31221.rs:31:9 | +LL | (Var1, b) => (), + | --------- matches some of the same values LL | (c, d) => (), - | ------ matches any value + | ------ matches some of the same values LL | anything => () | ^^^^^^^^ unreachable pattern diff --git a/tests/ui/pattern/usefulness/issue-57472.stderr b/tests/ui/pattern/usefulness/issue-57472.stderr index c814eaec0d1..68b5b7cb791 100644 --- a/tests/ui/pattern/usefulness/issue-57472.stderr +++ b/tests/ui/pattern/usefulness/issue-57472.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/issue-57472.rs:15:13 | +LL | Punned { foo: [_], .. } => println!("foo"), + | ----------------------- matches all the values already LL | Punned { bar: [_], .. } => println!("bar"), - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-57472.rs:2:9 @@ -13,8 +15,10 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/issue-57472.rs:32:17 | +LL | Punned { foo: [_] } => println!("foo"), + | ------------------- matches all the values already LL | Punned { bar: [_] } => println!("bar"), - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ unreachable pattern error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/match-arm-statics.stderr b/tests/ui/pattern/usefulness/match-arm-statics.stderr index a5dffebf699..37f1ac58a16 100644 --- a/tests/ui/pattern/usefulness/match-arm-statics.stderr +++ b/tests/ui/pattern/usefulness/match-arm-statics.stderr @@ -1,8 +1,11 @@ error: unreachable pattern --> $DIR/match-arm-statics.rs:25:9 | +LL | TRUE_TRUE => (), + | --------- matches all the values already +... LL | (true, true) => () - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-arm-statics.rs:2:9 @@ -13,14 +16,23 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/match-arm-statics.rs:40:9 | +LL | Some(Some(EAST)) => (), + | ---------------- matches all the values already +... LL | Some(Some(East)) => (), - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-arm-statics.rs:60:9 | +LL | Foo { bar: _, baz: NEW_FALSE } => (), + | ------------------------------ matches some of the same values +... +LL | Foo { bar: Some(EAST), .. } => (), + | --------------------------- matches some of the same values +LL | Foo { bar: Some(North), baz: NewBool(true) } => (), LL | Foo { bar: Some(EAST), baz: NewBool(false) } => () - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr index 0c582be8df8..39675e2bdd4 100644 --- a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:8:9 | +LL | b"AAAA" => {}, + | ------- matches all the values already LL | &[0x41, 0x41, 0x41, 0x41] => {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-byte-array-patterns.rs:1:9 @@ -13,44 +15,58 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:14:9 | +LL | &[0x41, 0x41, 0x41, 0x41] => {} + | ------------------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:20:9 | +LL | &[_, 0x41, 0x41, 0x41] => {}, + | ---------------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:26:9 | +LL | &[0x41, .., 0x41] => {} + | ----------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:34:9 | +LL | b"AAAA" => {}, + | ------- matches all the values already LL | &[0x41, 0x41, 0x41, 0x41] => {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:40:9 | +LL | &[0x41, 0x41, 0x41, 0x41] => {} + | ------------------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:46:9 | +LL | &[_, 0x41, 0x41, 0x41] => {}, + | ---------------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-byte-array-patterns.rs:52:9 | +LL | &[0x41, .., 0x41] => {} + | ----------------- matches all the values already LL | b"AAAA" => {}, - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: aborting due to 8 previous errors diff --git a/tests/ui/pattern/usefulness/match-ref-ice.stderr b/tests/ui/pattern/usefulness/match-ref-ice.stderr index 0dbfa776f69..9c5af47cc1e 100644 --- a/tests/ui/pattern/usefulness/match-ref-ice.stderr +++ b/tests/ui/pattern/usefulness/match-ref-ice.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/match-ref-ice.rs:13:9 | +LL | [1, ref _madoka, 3] => (), + | ------------------- matches all the values already LL | [1, 2, 3] => (), - | ^^^^^^^^^ + | ^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-ref-ice.rs:1:9 diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.stderr b/tests/ui/pattern/usefulness/match-vec-fixed.stderr index e388a06cb9a..04507a22856 100644 --- a/tests/ui/pattern/usefulness/match-vec-fixed.stderr +++ b/tests/ui/pattern/usefulness/match-vec-fixed.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/match-vec-fixed.rs:7:9 | LL | [_, _, _] => {} - | ^^^^^^^^^ + | --------- matches all the values already +LL | [_, _, _] => {} + | ^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-vec-fixed.rs:1:9 @@ -14,7 +16,9 @@ error: unreachable pattern --> $DIR/match-vec-fixed.rs:11:9 | LL | [_, 1, _] => {} - | ^^^^^^^^^ + | --------- matches all the values already +LL | [_, 1, _] => {} + | ^^^^^^^^^ unreachable pattern error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr index 672fd92fb5e..865f5b319a7 100644 --- a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr +++ b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/match-vec-unreachable.rs:8:9 | +LL | [a, (2, 3), _] => (), + | -------------- matches all the values already LL | [(1, 2), (2, 3), b] => (), - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/match-vec-unreachable.rs:1:9 @@ -13,14 +15,18 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/match-vec-unreachable.rs:18:9 | +LL | [ref a, _, _, ..] => { println!("{}", a); } + | ----------------- matches all the values already LL | [_, _, _, _, _] => { } - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/match-vec-unreachable.rs:26:9 | +LL | ['a', 'b', 'c', ref _tail @ ..] => {} + | ------------------------------- matches all the values already LL | ['a', 'b', 'c'] => {} - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ unreachable pattern error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr index dcad11a38a7..12db48590a4 100644 --- a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr +++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr @@ -1,8 +1,11 @@ error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:9:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already +LL | [0x00, 0x00, 0x00, 0x00] => (), LL | [4, 5, 6, 7] => (), - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/slice-pattern-const-2.rs:1:9 @@ -13,20 +16,26 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:15:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already LL | [4, 5, 6, 7] => (), - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:21:9 | +LL | [4, 5, 6, 7] => (), + | ------------ matches all the values already LL | MAGIC_TEST => (), - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const-2.rs:28:9 | +LL | [4] => (), + | --- matches all the values already LL | FOO => (), - | ^^^ + | ^^^ unreachable pattern error: aborting due to 4 previous errors diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr index b90b3a88a18..5a66799d9c9 100644 --- a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr +++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr @@ -1,8 +1,11 @@ error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:9:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already +LL | ["0x00", "0x00", "0x00", "0x00"] => (), LL | ["4", "5", "6", "7"] => (), - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/slice-pattern-const-3.rs:1:9 @@ -13,20 +16,26 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:15:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already LL | ["4", "5", "6", "7"] => (), - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:21:9 | +LL | ["4", "5", "6", "7"] => (), + | -------------------- matches all the values already LL | MAGIC_TEST => (), - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const-3.rs:28:9 | +LL | ["boo"] => (), + | ------- matches all the values already LL | FOO => (), - | ^^^ + | ^^^ unreachable pattern error: aborting due to 4 previous errors diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.stderr b/tests/ui/pattern/usefulness/slice-pattern-const.stderr index 1fffb9fedbf..87a85acc4c5 100644 --- a/tests/ui/pattern/usefulness/slice-pattern-const.stderr +++ b/tests/ui/pattern/usefulness/slice-pattern-const.stderr @@ -1,8 +1,11 @@ error: unreachable pattern --> $DIR/slice-pattern-const.rs:9:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already +LL | [0x00, 0x00, 0x00, 0x00] => (), LL | [84, 69, 83, 84] => (), - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/slice-pattern-const.rs:1:9 @@ -13,50 +16,68 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/slice-pattern-const.rs:15:9 | +LL | MAGIC_TEST => (), + | ---------- matches all the values already LL | [84, 69, 83, 84] => (), - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:21:9 | +LL | [84, 69, 83, 84] => (), + | ---------------- matches all the values already LL | MAGIC_TEST => (), - | ^^^^^^^^^^ + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:28:9 | +LL | [4] => (), + | --- matches all the values already LL | FOO => (), - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:35:9 | +LL | [4] => (), + | --- matches all the values already LL | BAR => (), - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:43:9 | +LL | [] => (), + | -- matches all the values already LL | BOO => (), - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:44:9 | +LL | [] => (), + | -- matches all the values already +LL | BOO => (), LL | b"" => (), - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:45:9 | +LL | [] => (), + | -- matches all the values already +... LL | _ => (), - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/slice-pattern-const.rs:51:9 | +LL | CONST1 => {} + | ------ matches all the values already LL | [true] => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: aborting due to 9 previous errors diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr index 607ffb76595..40fbb00de1f 100644 --- a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr +++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:8:9 | LL | [true, ..] => {} - | ^^^^^^^^^^ + | ---------- matches all the values already +LL | [true, ..] => {} + | ^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/slice-patterns-reachability.rs:1:9 @@ -13,32 +15,45 @@ LL | #![deny(unreachable_patterns)] error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:9:9 | +LL | [true, ..] => {} + | ---------- matches all the values already +LL | [true, ..] => {} LL | [true] => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:14:9 | LL | [.., true] => {} - | ^^^^^^^^^^ + | ---------- matches all the values already +LL | [.., true] => {} + | ^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:15:9 | +LL | [.., true] => {} + | ---------- matches all the values already +LL | [.., true] => {} LL | [true] => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:20:9 | LL | [false, .., true] => {} - | ^^^^^^^^^^^^^^^^^ + | ----------------- matches all the values already +LL | [false, .., true] => {} + | ^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/slice-patterns-reachability.rs:21:9 | +LL | [false, .., true] => {} + | ----------------- matches all the values already +LL | [false, .., true] => {} LL | [false, true] => {} - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ unreachable pattern error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/usefulness/top-level-alternation.stderr b/tests/ui/pattern/usefulness/top-level-alternation.stderr index 17fa951c539..0e7e7d4969d 100644 --- a/tests/ui/pattern/usefulness/top-level-alternation.stderr +++ b/tests/ui/pattern/usefulness/top-level-alternation.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/top-level-alternation.rs:4:23 | LL | while let 0..=2 | 1 = 0 {} - | ^ + | ----- ^ unreachable pattern + | | + | matches all the values already | note: the lint level is defined here --> $DIR/top-level-alternation.rs:1:9 @@ -14,61 +16,84 @@ error: unreachable pattern --> $DIR/top-level-alternation.rs:5:20 | LL | if let 0..=2 | 1 = 0 {} - | ^ + | ----- ^ unreachable pattern + | | + | matches all the values already error: unreachable pattern --> $DIR/top-level-alternation.rs:9:15 | +LL | 0 + | - matches all the values already LL | | 0 => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:14:15 | +LL | Some(0) + | ------- matches all the values already LL | | Some(0) => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:19:9 | +LL | (0, _) | (_, 0) => {} + | --------------- matches all the values already LL | (0, 0) => {} - | ^^^^^^ + | ^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:39:9 | +LL | None | Some(_) => {} + | -------------- matches all the values already LL | _ => {} - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:43:9 | +LL | None | Some(_) => {} + | -------------- matches all the values already LL | Some(_) => {} - | ^^^^^^^ + | ^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:44:9 | +LL | None | Some(_) => {} + | -------------- matches all the values already +LL | Some(_) => {} LL | None => {} - | ^^^^ + | ^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:49:9 | +LL | Some(_) => {} + | ------- matches some of the same values +LL | None => {} + | ---- matches some of the same values LL | None | Some(_) => {} - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:53:9 | +LL | 1 | 2 => {}, + | ----- matches all the values already LL | 1..=2 => {}, - | ^^^^^ + | ^^^^^ unreachable pattern error: unreachable pattern --> $DIR/top-level-alternation.rs:56:14 | LL | let (0 | 0) = 0 else { return }; - | ^ + | - ^ unreachable pattern + | | + | matches all the values already error: aborting due to 11 previous errors diff --git a/tests/ui/reachable/unreachable-arm.stderr b/tests/ui/reachable/unreachable-arm.stderr index 60db8217640..79627404030 100644 --- a/tests/ui/reachable/unreachable-arm.stderr +++ b/tests/ui/reachable/unreachable-arm.stderr @@ -1,8 +1,10 @@ error: unreachable pattern --> $DIR/unreachable-arm.rs:11:9 | +LL | Foo::B(_) | Foo::A(box _, 1) => { } + | ---------------------------- matches all the values already LL | Foo::A(_, 1) => { } - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/unreachable-arm.rs:4:9 diff --git a/tests/ui/reachable/unreachable-loop-patterns.stderr b/tests/ui/reachable/unreachable-loop-patterns.stderr index 1dea9d813f9..bdd9b5ee411 100644 --- a/tests/ui/reachable/unreachable-loop-patterns.stderr +++ b/tests/ui/reachable/unreachable-loop-patterns.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | for _ in unimplemented!() as Void {} | ^ | + = note: this pattern matches no values because `Void` is uninhabited note: the lint level is defined here --> $DIR/unreachable-loop-patterns.rs:5:9 | diff --git a/tests/ui/reachable/unreachable-try-pattern.stderr b/tests/ui/reachable/unreachable-try-pattern.stderr index 8f3e23119fb..bc1a6fffda6 100644 --- a/tests/ui/reachable/unreachable-try-pattern.stderr +++ b/tests/ui/reachable/unreachable-try-pattern.stderr @@ -19,6 +19,7 @@ warning: unreachable pattern LL | let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; | ^^^^^ | + = note: this pattern matches no values because `!` is uninhabited note: the lint level is defined here --> $DIR/unreachable-try-pattern.rs:4:9 | @@ -30,6 +31,8 @@ warning: unreachable pattern | LL | let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?; | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited warning: 3 warnings emitted diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr index fe2a72d2a31..a875041d89c 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | Err(!), | ^^^^^^ | + = note: this pattern matches no values because `Void` is uninhabited note: the lint level is defined here --> $DIR/unreachable.rs:7:9 | @@ -15,30 +16,40 @@ error: unreachable pattern | LL | let (Ok(_x) | Err(!)) = res_void; | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/unreachable.rs:22:12 | LL | if let Err(!) = res_void {} | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/unreachable.rs:24:24 | LL | if let (Ok(true) | Err(!)) = res_void {} | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/unreachable.rs:26:23 | LL | for (Ok(mut _x) | Err(!)) in [res_void] {} | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: unreachable pattern --> $DIR/unreachable.rs:30:18 | LL | fn foo((Ok(_x) | Err(!)): Result) {} | ^^^^^^ + | + = note: this pattern matches no values because `Void` is uninhabited error: aborting due to 6 previous errors diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr index 7386f10a6fb..d5f58e436c5 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | _ => {} | ^ | + = note: this pattern matches no values because `EmptyNonExhaustiveEnum` is uninhabited note: the lint level is defined here --> $DIR/enum_same_crate_empty_match.rs:1:9 | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr index 3034a67dc43..4ec4ec9705a 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr @@ -2,7 +2,9 @@ error: unreachable pattern --> $DIR/issue-65157-repeated-match-arm.rs:15:9 | LL | PartiallyInhabitedVariants::Struct { .. } => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------------------------- matches all the values already +LL | PartiallyInhabitedVariants::Struct { .. } => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-65157-repeated-match-arm.rs:2:9 diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index 8bfd6e91f4d..d5192a70ed5 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | Some(_x) => (), | ^^^^^^^^ | + = note: this pattern matches no values because `UninhabitedEnum` is uninhabited note: the lint level is defined here --> $DIR/patterns_same_crate.rs:1:9 | @@ -15,24 +16,32 @@ error: unreachable pattern | LL | Some(_x) => (), | ^^^^^^^^ + | + = note: this pattern matches no values because `UninhabitedVariants` is uninhabited error: unreachable pattern --> $DIR/patterns_same_crate.rs:61:15 | LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern matches no values because `!` is uninhabited error: unreachable pattern --> $DIR/patterns_same_crate.rs:65:15 | LL | while let Some(_x) = uninhabited_struct() { | ^^^^^^^^ + | + = note: this pattern matches no values because `UninhabitedStruct` is uninhabited error: unreachable pattern --> $DIR/patterns_same_crate.rs:68:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { | ^^^^^^^^ + | + = note: this pattern matches no values because `UninhabitedTupleStruct` is uninhabited error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr index eed5dbb88de..8d0874fa900 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/warns.stderr @@ -16,7 +16,9 @@ error: unreachable pattern --> $DIR/warns.rs:15:25 | LL | x if let None | None = x => {} - | ^^^^ + | ---- ^^^^ unreachable pattern + | | + | matches all the values already | note: the lint level is defined here --> $DIR/warns.rs:12:8 diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr index a6fda88f032..ca62386d7ef 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.stderr +++ b/tests/ui/uninhabited/uninhabited-patterns.stderr @@ -4,6 +4,7 @@ error: unreachable pattern LL | Ok(box _) => (), | ^^^^^^^^^ | + = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited note: the lint level is defined here --> $DIR/uninhabited-patterns.rs:4:9 | @@ -15,12 +16,16 @@ error: unreachable pattern | LL | Err(Ok(_y)) => (), | ^^^^^^^^^^^ + | + = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited error: unreachable pattern --> $DIR/uninhabited-patterns.rs:42:15 | LL | while let Some(_y) = foo() { | ^^^^^^^^ + | + = note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5