From aab3b9327ed2233da15e57b1d552473549e15300 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 14 Oct 2023 00:57:50 +0200 Subject: [PATCH 1/3] Propagate pattern errors via a new `PatKind::Error` variant Instead of via `Const::new_error` --- compiler/rustc_middle/src/thir.rs | 31 ++++++++++++++++--- compiler/rustc_middle/src/thir/visit.rs | 2 +- .../rustc_mir_build/src/build/matches/mod.rs | 5 ++- .../src/build/matches/simplify.rs | 2 +- .../rustc_mir_build/src/build/matches/test.rs | 6 ++-- .../rustc_mir_build/src/check_unsafety.rs | 3 +- .../src/thir/pattern/check_match.rs | 4 +-- .../src/thir/pattern/const_to_pat.rs | 22 +++++-------- .../src/thir/pattern/deconstruct_pat.rs | 4 +++ .../rustc_mir_build/src/thir/pattern/mod.rs | 1 + compiler/rustc_mir_build/src/thir/print.rs | 3 ++ .../typeid-equality-by-subtyping.stderr | 14 +-------- 12 files changed, 56 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 08f7434a4a9..67804998a32 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -19,11 +19,12 @@ use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp}; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarArgs}; -use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation}; +use rustc_middle::ty::{ + self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty, + UpvarArgs, +}; use rustc_span::def_id::LocalDefId; -use rustc_span::{sym, Span, Symbol, DUMMY_SP}; +use rustc_span::{sym, ErrorGuaranteed, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::asm::InlineAsmRegOrRegClass; use std::fmt; @@ -632,7 +633,7 @@ fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) { use PatKind::*; match &self.kind { - Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {} + Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } | Error(_) => {} AscribeUserType { subpattern, .. } | Binding { subpattern: Some(subpattern), .. } | Deref { subpattern } => subpattern.walk_(it), @@ -647,6 +648,21 @@ fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) { } } + /// Whether the pattern has a `PatKind::Error` nested within. + pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> { + let mut error = None; + self.walk(|pat| { + if let PatKind::Error(e) = pat.kind && error.is_none() { + error = Some(e); + } + error.is_none() + }); + match error { + None => Ok(()), + Some(e) => Err(e), + } + } + /// Walk the pattern in left-to-right order. /// /// If you always want to recurse, prefer this method over `walk`. @@ -771,6 +787,10 @@ pub enum PatKind<'tcx> { Or { pats: Box<[Box>]>, }, + + /// An error has been encountered during lowering. We probably shouldn't report more lints + /// related to this pattern. + Error(ErrorGuaranteed), } #[derive(Clone, Debug, PartialEq, HashStable, TypeVisitable)] @@ -934,6 +954,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } Ok(()) } + PatKind::Error(_) => write!(f, ""), } } } diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index b84e1568884..afb58438519 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -226,7 +226,7 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' is_primary: _, name: _, } => visitor.visit_pat(&subpattern), - Binding { .. } | Wild => {} + Binding { .. } | Wild | Error(_) => {} Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => { for subpattern in subpatterns { visitor.visit_pat(&subpattern.pattern); diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index eb1c6a9824a..ab3ffabe297 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -814,7 +814,10 @@ pub(super) fn visit_primary_bindings( } } - PatKind::Constant { .. } | PatKind::Range { .. } | PatKind::Wild => {} + PatKind::Constant { .. } + | PatKind::Range { .. } + | PatKind::Wild + | PatKind::Error(_) => {} PatKind::Deref { ref subpattern } => { self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f); diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 17ac1f4e0ce..f340feb40d4 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -168,7 +168,7 @@ fn simplify_match_pair<'pat>( Ok(()) } - PatKind::Wild => { + PatKind::Wild | PatKind::Error(_) => { // nothing left to do Ok(()) } diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 795d1db8eec..dde3702ca63 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -77,7 +77,8 @@ pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test< | PatKind::Wild | PatKind::Binding { .. } | PatKind::Leaf { .. } - | PatKind::Deref { .. } => self.error_simplifiable(match_pair), + | PatKind::Deref { .. } + | PatKind::Error(_) => self.error_simplifiable(match_pair), } } @@ -111,7 +112,8 @@ pub(super) fn add_cases_to_switch<'pat>( | PatKind::Binding { .. } | PatKind::AscribeUserType { .. } | PatKind::Leaf { .. } - | PatKind::Deref { .. } => { + | PatKind::Deref { .. } + | PatKind::Error(_) => { // don't know how to add these patterns to a switch false } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 192bd4a83e3..6cf2ecc51e9 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -224,7 +224,8 @@ fn visit_pat(&mut self, pat: &Pat<'tcx>) { PatKind::Wild | // these just wrap other patterns PatKind::Or { .. } | - PatKind::AscribeUserType { .. } => {} + PatKind::AscribeUserType { .. } | + PatKind::Error(_) => {} } }; 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 93434dd3cc2..5caf37f5b06 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -19,7 +19,7 @@ use rustc_middle::thir::visit::{self, Visitor}; use rustc_middle::thir::*; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_session::lint::builtin::{ BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS, }; @@ -683,7 +683,7 @@ fn non_exhaustive_match<'p, 'tcx>( expr_span: Span, ) -> ErrorGuaranteed { for &arm in arms { - if let Err(err) = thir[arm].pattern.error_reported() { + if let Err(err) = thir[arm].pattern.pat_error_reported() { return err; } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index fde6defd87f..32d389c4354 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -196,9 +196,7 @@ fn to_pat( }; // All branches above emitted an error. Don't print any more lints. // We errored. Signal that in the pattern, so that follow up errors can be silenced. - let kind = PatKind::Constant { - value: mir::Const::Ty(ty::Const::new_error(self.tcx(), e, cv.ty())), - }; + let kind = PatKind::Error(e); return Box::new(Pat { span: self.span, ty: cv.ty(), kind }); } else if !self.saw_const_match_lint.get() { if let Some(mir_structural_match_violation) = mir_structural_match_violation { @@ -351,7 +349,7 @@ fn recur( let e = tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty }); self.saw_const_match_error.set(Some(e)); // We errored. Signal that in the pattern, so that follow up errors can be silenced. - PatKind::Constant { value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)) } + PatKind::Error(e) } ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,); @@ -359,7 +357,7 @@ fn recur( let e = tcx.sess.emit_err(err); self.saw_const_match_error.set(Some(e)); // We errored. Signal that in the pattern, so that follow up errors can be silenced. - PatKind::Constant { value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)) } + PatKind::Error(e) } ty::Adt(adt_def, args) if adt_def.is_enum() => { let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap(); @@ -434,17 +432,13 @@ fn recur( } else { if let Some(e) = self.saw_const_match_error.get() { // We already errored. Signal that in the pattern, so that follow up errors can be silenced. - PatKind::Constant { - value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)), - } + PatKind::Error(e) } else { let err = TypeNotStructural { span, non_sm_ty: *pointee_ty }; let e = tcx.sess.emit_err(err); self.saw_const_match_error.set(Some(e)); // We errored. Signal that in the pattern, so that follow up errors can be silenced. - PatKind::Constant { - value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)), - } + PatKind::Error(e) } } } @@ -456,9 +450,7 @@ fn recur( let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; let e = tcx.sess.emit_err(err); // We errored. Signal that in the pattern, so that follow up errors can be silenced. - PatKind::Constant { - value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)), - } + PatKind::Error(e) } else { let old = self.behind_reference.replace(true); // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when @@ -489,7 +481,7 @@ fn recur( let e = tcx.sess.emit_err(err); self.saw_const_match_error.set(Some(e)); // We errored. Signal that in the pattern, so that follow up errors can be silenced. - PatKind::Constant { value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)) } + PatKind::Error(e) } }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index a7a000ba31c..bbc0aeb66cf 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -1525,6 +1525,10 @@ pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self { let pats = expand_or_pat(pat); fields = Fields::from_iter(cx, pats.into_iter().map(mkpat)); } + PatKind::Error(_) => { + ctor = Opaque; + fields = Fields::empty(); + } } DeconstructedPat::new(ctor, fields, pat.ty, pat.span) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 25726c5a872..400ff16acce 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -791,6 +791,7 @@ fn fold_with>(&self, folder: &mut F) -> Self { fn super_fold_with>(&self, folder: &mut F) -> Self { match *self { PatKind::Wild => PatKind::Wild, + PatKind::Error(e) => PatKind::Error(e), PatKind::AscribeUserType { ref subpattern, ascription: Ascription { ref annotation, variance }, diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 3b6276cfeb0..c957611b975 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -757,6 +757,9 @@ fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) { print_indented!(self, "]", depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } + PatKind::Error(_) => { + print_indented!(self, "Error", depth_lvl + 1); + } } print_indented!(self, "}", depth_lvl); diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr index 69bc174b6be..8cbd1265448 100644 --- a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr +++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr @@ -7,17 +7,5 @@ LL | WHAT_A_TYPE => 0, = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error[E0015]: cannot match on `TypeId` in constant functions - --> $DIR/typeid-equality-by-subtyping.rs:18:9 - | -LL | WHAT_A_TYPE => 0, - | ^^^^^^^^^^^ - | - = note: `TypeId` cannot be compared in compile-time, and therefore cannot be used in `match`es -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +error: aborting due to previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0015`. From 8646afb9c5ddad4e7c6805390d5265db54203f0d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 14 Oct 2023 01:49:41 +0200 Subject: [PATCH 2/3] Use `PatKind::Error` instead of `PatKind::Wild` to report errors --- .../src/thir/pattern/check_match.rs | 6 +++ .../rustc_mir_build/src/thir/pattern/mod.rs | 41 +++++++++---------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 5caf37f5b06..064afed9f7d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -426,6 +426,12 @@ fn check_let_chain( #[instrument(level = "trace", skip(self))] fn check_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option) { + // If we got errors while lowering, don't emit anything more. + if let Err(err) = pat.pat_error_reported() { + self.error = Err(err); + return; + } + let mut cx = self.new_cx(self.lint_level, false); let pattern = self.lower_pattern(&mut cx, pat); diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 400ff16acce..76ed6d2b6d7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -252,10 +252,8 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box { let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref()); - // FIXME?: returning `_` can cause inaccurate "unreachable" warnings. This can be - // fixed by returning `PatKind::Const(ConstKind::Error(...))` if #115937 gets - // merged. - self.lower_pattern_range(lo_expr, hi_expr, end, ty, span).unwrap_or(PatKind::Wild) + self.lower_pattern_range(lo_expr, hi_expr, end, ty, span) + .unwrap_or_else(PatKind::Error) } hir::PatKind::Path(ref qpath) => { @@ -423,9 +421,9 @@ fn lower_variant_or_leaf( if adt_def.is_enum() { let args = match ty.kind() { ty::Adt(_, args) | ty::FnDef(_, args) => args, - ty::Error(_) => { + ty::Error(e) => { // Avoid ICE (#50585) - return PatKind::Wild; + return PatKind::Error(*e); } _ => bug!("inappropriate type for def: {:?}", ty), }; @@ -452,7 +450,7 @@ fn lower_variant_or_leaf( | Res::SelfTyAlias { .. } | Res::SelfCtor(..) => PatKind::Leaf { subpatterns }, _ => { - match res { + let e = match res { Res::Def(DefKind::ConstParam, _) => { self.tcx.sess.emit_err(ConstParamInPattern { span }) } @@ -461,7 +459,7 @@ fn lower_variant_or_leaf( } _ => self.tcx.sess.emit_err(NonConstPath { span }), }; - PatKind::Wild + PatKind::Error(e) } }; @@ -513,14 +511,13 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> // It should be assoc consts if there's no error but we cannot resolve it. debug_assert!(is_associated_const); - self.tcx.sess.emit_err(AssocConstInPattern { span }); - - return pat_from_kind(PatKind::Wild); + let e = self.tcx.sess.emit_err(AssocConstInPattern { span }); + return pat_from_kind(PatKind::Error(e)); } Err(_) => { - self.tcx.sess.emit_err(CouldNotEvalConstPattern { span }); - return pat_from_kind(PatKind::Wild); + let e = self.tcx.sess.emit_err(CouldNotEvalConstPattern { span }); + return pat_from_kind(PatKind::Error(e)); } }; @@ -574,12 +571,12 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Err(ErrorHandled::TooGeneric(_)) => { // While `Reported | Linted` cases will have diagnostics emitted already // it is not true for TooGeneric case, so we need to give user more information. - self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); - pat_from_kind(PatKind::Wild) + let e = self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); + pat_from_kind(PatKind::Error(e)) } Err(_) => { - self.tcx.sess.emit_err(CouldNotEvalConstPattern { span }); - pat_from_kind(PatKind::Wild) + let e = self.tcx.sess.emit_err(CouldNotEvalConstPattern { span }); + pat_from_kind(PatKind::Error(e)) } } } @@ -629,7 +626,7 @@ fn lower_inline_const( let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), args, promoted: None }; debug_assert!(!args.has_free_regions()); - let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args: args }; + let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args }; // First try using a valtree in order to destructure the constant into a pattern. // FIXME: replace "try to do a thing, then fall back to another thing" // but something more principled, like a trait query checking whether this can be turned into a valtree. @@ -649,10 +646,10 @@ fn lower_inline_const( Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span, None).kind, Err(ErrorHandled::TooGeneric(_)) => { // If we land here it means the const can't be evaluated because it's `TooGeneric`. - self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); - PatKind::Wild + let e = self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); + PatKind::Error(e) } - Err(ErrorHandled::Reported(..)) => PatKind::Wild, + Err(ErrorHandled::Reported(err, ..)) => PatKind::Error(err.into()), } } } @@ -685,7 +682,7 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> { Ok(constant) => { self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span, None).kind } - Err(LitToConstError::Reported(_)) => PatKind::Wild, + Err(LitToConstError::Reported(e)) => PatKind::Error(e), Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } } From 89f75ff4d05d22ca3b9b3d70fc6bcd225c8dbf12 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 14 Oct 2023 03:06:18 +0200 Subject: [PATCH 3/3] Skip most of check_match checks in the presence of `PatKind::Error` --- .../src/thir/pattern/check_match.rs | 26 ++++++--- tests/ui/pattern/usefulness/consts-opaque.rs | 2 - .../pattern/usefulness/consts-opaque.stderr | 55 ++++++------------- 3 files changed, 35 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 064afed9f7d..bcecd0ff9db 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -231,6 +231,10 @@ fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: ExprId, source: LetSource, s if let LetSource::None = source { return; } + if let Err(err) = pat.pat_error_reported() { + self.error = Err(err); + return; + } self.check_patterns(pat, Refutable); let mut cx = self.new_cx(self.lint_level, true); let tpat = self.lower_pattern(&mut cx, pat); @@ -252,6 +256,10 @@ fn check_match( self.with_lint_level(arm.lint_level, |this| { this.check_patterns(&arm.pattern, Refutable); }); + if let Err(err) = arm.pattern.pat_error_reported() { + self.error = Err(err); + return; + } } let tarms: Vec<_> = arms @@ -334,7 +342,8 @@ fn check_let_chain( // and record chain members that aren't let exprs. let mut chain_refutabilities = Vec::new(); - let add = |expr: ExprId, mut local_lint_level| { + let mut error = Ok(()); + let mut add = |expr: ExprId, mut local_lint_level| { // `local_lint_level` is the lint level enclosing the pattern inside `expr`. let mut expr = &self.thir[expr]; debug!(?expr, ?local_lint_level, "add"); @@ -348,6 +357,10 @@ fn check_let_chain( debug!(?expr, ?local_lint_level, "after scopes"); match expr.kind { ExprKind::Let { box ref pat, expr: _ } => { + if let Err(err) = pat.pat_error_reported() { + error = Err(err); + return None; + } let mut ncx = self.new_cx(local_lint_level, true); let tpat = self.lower_pattern(&mut ncx, pat); let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat); @@ -380,6 +393,11 @@ fn check_let_chain( debug!(?chain_refutabilities); chain_refutabilities.reverse(); + if error.is_err() { + self.error = error; + return; + } + // Third, emit the actual warnings. if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, false)))) { // The entire chain is made up of irrefutable `let` statements @@ -688,12 +706,6 @@ fn non_exhaustive_match<'p, 'tcx>( arms: &[ArmId], expr_span: Span, ) -> ErrorGuaranteed { - for &arm in arms { - if let Err(err) = thir[arm].pattern.pat_error_reported() { - return err; - } - } - let is_empty_match = arms.is_empty(); let non_empty_enum = match scrut_ty.kind() { ty::Adt(def, _) => def.is_enum() && !def.variants().is_empty(), diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs index 2032cf13bc2..6dc1425cf03 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.rs +++ b/tests/ui/pattern/usefulness/consts-opaque.rs @@ -52,7 +52,6 @@ fn main() { BAR => {} //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` _ => {} - //~^ ERROR unreachable pattern } match BAR { @@ -60,7 +59,6 @@ fn main() { //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` Bar => {} _ => {} - //~^ ERROR unreachable pattern } match BAR { diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index cd88e6a22e4..51f2f276bbe 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -38,7 +38,16 @@ LL | BAR => {} = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:59:9 + --> $DIR/consts-opaque.rs:58:9 + | +LL | BAR => {} + | ^^^ + | + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details + +error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:65:9 | LL | BAR => {} | ^^^ @@ -55,17 +64,8 @@ LL | BAR => {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:69:9 - | -LL | BAR => {} - | ^^^ - | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details - error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:75:9 + --> $DIR/consts-opaque.rs:73:9 | LL | BAZ => {} | ^^^ @@ -74,7 +74,7 @@ LL | BAZ => {} = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:83:9 + --> $DIR/consts-opaque.rs:81:9 | LL | BAZ => {} | ^^^ @@ -83,7 +83,7 @@ LL | BAZ => {} = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/consts-opaque.rs:89:9 + --> $DIR/consts-opaque.rs:87:9 | LL | BAZ => {} | ^^^ @@ -91,37 +91,14 @@ LL | BAZ => {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: unreachable pattern - --> $DIR/consts-opaque.rs:54:9 - | -LL | Bar => {} - | --- matches any value -... -LL | _ => {} - | ^ unreachable pattern - | -note: the lint level is defined here - --> $DIR/consts-opaque.rs:6:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/consts-opaque.rs:62:9 - | -LL | Bar => {} - | --- matches any value -LL | _ => {} - | ^ unreachable pattern - error[E0004]: non-exhaustive patterns: `Wrap(_)` not covered - --> $DIR/consts-opaque.rs:124:11 + --> $DIR/consts-opaque.rs:122:11 | LL | match WRAPQUUX { | ^^^^^^^^ pattern `Wrap(_)` not covered | note: `Wrap usize>` defined here - --> $DIR/consts-opaque.rs:106:12 + --> $DIR/consts-opaque.rs:104:12 | LL | struct Wrap(T); | ^^^^ @@ -132,6 +109,6 @@ LL ~ WRAPQUUX => {}, LL + Wrap(_) => todo!() | -error: aborting due to 12 previous errors; 1 warning emitted +error: aborting due to 10 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0004`.