diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index cd00d181ed04..e7c3a366cc43 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -267,6 +267,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { if let ty::Adt(def, _) = place_ty.kind() { if def.variants.len() > 1 { needs_to_be_read = true; + } else if let Some(variant) = def.variants.iter().next() { + // If the pat kind is a Path we want to check whether the + // variant contains at least one field. If that's the case, + // we want to borrow discr. + if matches!(pat.kind, PatKind::Path(..)) && variant.fields.len() > 0 { + needs_to_be_read = true; + } } } else { // If it is not ty::Adt, then it should be read diff --git a/src/test/ui/closures/2229_closure_analysis/issue-88331.rs b/src/test/ui/closures/2229_closure_analysis/issue-88331.rs new file mode 100644 index 000000000000..0a6d71c68ae8 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-88331.rs @@ -0,0 +1,33 @@ +// edition:2021 + +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct Opcode(pub u8); + +impl Opcode { + pub const OP1: Opcode = Opcode(0x1); +} + +pub fn example1(msg_type: Opcode) -> impl FnMut(&[u8]) { + move |i| match msg_type { + //~^ ERROR: non-exhaustive patterns: `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered + Opcode::OP1 => unimplemented!(), + } +} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct Opcode2(Opcode); + +impl Opcode2 { + pub const OP2: Opcode2 = Opcode2(Opcode(0x1)); +} + + +pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { + + move |i| match msg_type { + //~^ ERROR: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered + Opcode2::OP2=> unimplemented!(), + } +} + +fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/issue-88331.stderr b/src/test/ui/closures/2229_closure_analysis/issue-88331.stderr new file mode 100644 index 000000000000..f02d23464f16 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-88331.stderr @@ -0,0 +1,27 @@ +error[E0004]: non-exhaustive patterns: `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered + --> $DIR/issue-88331.rs:11:20 + | +LL | pub struct Opcode(pub u8); + | -------------------------- `Opcode` defined here +... +LL | move |i| match msg_type { + | ^^^^^^^^ patterns `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Opcode` + +error[E0004]: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered + --> $DIR/issue-88331.rs:27:20 + | +LL | pub struct Opcode2(Opcode); + | --------------------------- `Opcode2` defined here +... +LL | move |i| match msg_type { + | ^^^^^^^^ patterns `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Opcode2` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`.