diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 8c39614903cb0..694a273fcfff0 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -581,13 +581,13 @@ pub enum BindingMode { ByRef(BorrowKind), } -#[derive(Clone, Debug, HashStable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct FieldPat<'tcx> { pub field: FieldIdx, pub pattern: Box>, } -#[derive(Clone, Debug, HashStable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct Pat<'tcx> { pub ty: Ty<'tcx>, pub span: Span, @@ -664,7 +664,7 @@ impl<'tcx> IntoDiagnosticArg for Pat<'tcx> { } } -#[derive(Clone, Debug, HashStable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct Ascription<'tcx> { pub annotation: CanonicalUserTypeAnnotation<'tcx>, /// Variance to use when relating the `user_ty` to the **type of the value being @@ -688,7 +688,7 @@ pub struct Ascription<'tcx> { pub variance: ty::Variance, } -#[derive(Clone, Debug, HashStable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub enum PatKind<'tcx> { /// A wildcard pattern: `_`. Wild, @@ -702,7 +702,9 @@ pub enum PatKind<'tcx> { Binding { mutability: Mutability, name: Symbol, + #[type_visitable(ignore)] mode: BindingMode, + #[type_visitable(ignore)] var: LocalVarId, ty: Ty<'tcx>, subpattern: Option>>, @@ -767,10 +769,11 @@ pub enum PatKind<'tcx> { }, } -#[derive(Clone, Debug, PartialEq, HashStable)] +#[derive(Clone, Debug, PartialEq, HashStable, TypeVisitable)] pub struct PatRange<'tcx> { pub lo: mir::Const<'tcx>, pub hi: mir::Const<'tcx>, + #[type_visitable(ignore)] pub end: RangeEnd, } 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 95dced644e161..22290fc4c4025 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_hir::HirId; 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}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::lint::builtin::{ BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS, }; @@ -682,6 +682,12 @@ fn non_exhaustive_match<'p, 'tcx>( arms: &[ArmId], expr_span: Span, ) -> ErrorGuaranteed { + for &arm in arms { + if let Err(err) = thir[arm].pattern.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/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index f36f4ec8697fa..f1037fe0bafa5 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -153,6 +153,12 @@ impl> TypeVisitable for &[T] { } } +impl> TypeVisitable for Box<[T]> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + impl, Ix: Idx> TypeFoldable for IndexVec { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|x| x.try_fold_with(folder)) diff --git a/tests/ui/consts/match_ice.rs b/tests/ui/consts/match_ice.rs index bb31fe2212616..632335c841e3a 100644 --- a/tests/ui/consts/match_ice.rs +++ b/tests/ui/consts/match_ice.rs @@ -7,7 +7,7 @@ struct T; fn main() { const C: &S = &S; - match C { //~ ERROR: non-exhaustive patterns: `&_` not covered + match C { C => {} //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` } diff --git a/tests/ui/consts/match_ice.stderr b/tests/ui/consts/match_ice.stderr index cb0d22303ac89..342d94ed31c87 100644 --- a/tests/ui/consts/match_ice.stderr +++ b/tests/ui/consts/match_ice.stderr @@ -7,24 +7,5 @@ LL | C => {} = 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[E0004]: non-exhaustive patterns: `&_` not covered - --> $DIR/match_ice.rs:10:11 - | -LL | match C { - | ^ pattern `&_` not covered - | -note: `S` defined here - --> $DIR/match_ice.rs:3:8 - | -LL | struct S; - | ^ - = note: the matched value is of type `&S` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ C => {}, -LL + &_ => todo!() - | - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/issue-72565.rs b/tests/ui/pattern/issue-72565.rs index a9a5427d2ca5b..21edb26de082e 100644 --- a/tests/ui/pattern/issue-72565.rs +++ b/tests/ui/pattern/issue-72565.rs @@ -2,7 +2,7 @@ const F: &'static dyn PartialEq = &7u32; fn main() { let a: &dyn PartialEq = &7u32; - match a { //~ ERROR: non-exhaustive patterns: `&_` not covered + match a { F => panic!(), //~ ERROR: `dyn PartialEq` cannot be used in patterns } } diff --git a/tests/ui/pattern/issue-72565.stderr b/tests/ui/pattern/issue-72565.stderr index fc9ffc0630115..0519720694d70 100644 --- a/tests/ui/pattern/issue-72565.stderr +++ b/tests/ui/pattern/issue-72565.stderr @@ -4,18 +4,5 @@ error: `dyn PartialEq` cannot be used in patterns LL | F => panic!(), | ^ -error[E0004]: non-exhaustive patterns: `&_` not covered - --> $DIR/issue-72565.rs:5:11 - | -LL | match a { - | ^ pattern `&_` not covered - | - = note: the matched value is of type `&dyn PartialEq` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL | F => panic!(), &_ => todo!(), - | +++++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs index e822a402931b8..fc52ee3d013c1 100644 --- a/tests/ui/pattern/non-structural-match-types.rs +++ b/tests/ui/pattern/non-structural-match-types.rs @@ -5,10 +5,10 @@ #![feature(inline_const_pat)] fn main() { - match loop {} { //~ ERROR: non-exhaustive patterns: `_` not covered - const { || {} } => {}, //~ ERROR cannot be used in patterns + match loop {} { + const { || {} } => {} //~ ERROR cannot be used in patterns } - match loop {} { //~ ERROR: non-exhaustive patterns: `_` not covered - const { async {} } => {}, //~ ERROR cannot be used in patterns + match loop {} { + const { async {} } => {} //~ ERROR cannot be used in patterns } } diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr index 984dd3fbc1564..f3e0665fef51d 100644 --- a/tests/ui/pattern/non-structural-match-types.stderr +++ b/tests/ui/pattern/non-structural-match-types.stderr @@ -1,39 +1,14 @@ error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns --> $DIR/non-structural-match-types.rs:9:9 | -LL | const { || {} } => {}, +LL | const { || {} } => {} | ^^^^^^^^^^^^^^^ error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` cannot be used in patterns --> $DIR/non-structural-match-types.rs:12:9 | -LL | const { async {} } => {}, +LL | const { async {} } => {} | ^^^^^^^^^^^^^^^^^^ -error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/non-structural-match-types.rs:8:11 - | -LL | match loop {} { - | ^^^^^^^ pattern `_` not covered - | - = note: the matched value is of type `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL | const { || {} } => {}, _ => todo!(), - | ++++++++++++++ - -error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/non-structural-match-types.rs:11:11 - | -LL | match loop {} { - | ^^^^^^^ pattern `_` not covered - | - = note: the matched value is of type `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL | const { async {} } => {}, _ => todo!(), - | ++++++++++++++ - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs index 91a5e5a58e1dc..151a475c91906 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs @@ -12,7 +12,7 @@ struct B(i32); fn main() { const FOO: [B; 1] = [B(0)]; - match [B(1)] { //~ ERROR: non-exhaustive patterns: `[_]` not covered + match [B(1)] { FOO => { } //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr index 5b81af98dfa88..6adebada0437d 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr @@ -7,19 +7,5 @@ LL | FOO => { } = 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[E0004]: non-exhaustive patterns: `[_]` not covered - --> $DIR/match-nonempty-array-forbidden-without-eq.rs:15:11 - | -LL | match [B(1)] { - | ^^^^^^ pattern `[_]` not covered - | - = note: the matched value is of type `[B; 1]` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ FOO => { }, -LL + [_] => todo!() - | - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0004`.