mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Add note when matching on nested non-exhaustive enums
This commit is contained in:
parent
a293619caa
commit
43dd8613a3
@ -720,15 +720,8 @@ fn non_exhaustive_match<'p, 'tcx>(
|
||||
};
|
||||
};
|
||||
|
||||
let is_variant_list_non_exhaustive = matches!(scrut_ty.kind(),
|
||||
ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local());
|
||||
|
||||
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
|
||||
err.note(format!(
|
||||
"the matched value is of type `{}`{}",
|
||||
scrut_ty,
|
||||
if is_variant_list_non_exhaustive { ", which is marked as non-exhaustive" } else { "" }
|
||||
));
|
||||
err.note(format!("the matched value is of type `{}`", scrut_ty));
|
||||
|
||||
if !is_empty_match && witnesses.len() == 1 {
|
||||
let mut non_exhaustive_tys = FxHashSet::default();
|
||||
@ -750,6 +743,8 @@ fn non_exhaustive_match<'p, 'tcx>(
|
||||
err.note(format!(
|
||||
"`{ty}` cannot be matched exhaustively, so a wildcard `_` is necessary",
|
||||
));
|
||||
} else if cx.is_foreign_non_exhaustive_enum(ty) {
|
||||
err.note(format!("`{ty}` is marked as non-exhaustive"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -618,10 +618,15 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
|
||||
let new_witnesses = if let Constructor::Missing { .. } = ctor {
|
||||
// We got the special `Missing` constructor, so each of the missing constructors
|
||||
// gives a new pattern that is not caught by the match. We list those patterns.
|
||||
let new_patterns = if pcx.is_non_exhaustive {
|
||||
if pcx.is_non_exhaustive {
|
||||
witnesses
|
||||
.into_iter()
|
||||
// Here we don't want the user to try to list all variants, we want them to add
|
||||
// a wildcard, so we only suggest that.
|
||||
vec![DeconstructedPat::wildcard(pcx.ty, pcx.span)]
|
||||
.map(|witness| {
|
||||
witness.apply_constructor(pcx, &Constructor::NonExhaustive)
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
let mut split_wildcard = SplitWildcard::new(pcx);
|
||||
split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor));
|
||||
@ -633,7 +638,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
|
||||
// constructor, that matches everything that can be built with
|
||||
// it. For example, if `ctor` is a `Constructor::Variant` for
|
||||
// `Option::Some`, we get the pattern `Some(_)`.
|
||||
let mut new: Vec<DeconstructedPat<'_, '_>> = split_wildcard
|
||||
let mut new_patterns: Vec<DeconstructedPat<'_, '_>> = split_wildcard
|
||||
.iter_missing(pcx)
|
||||
.filter_map(|missing_ctor| {
|
||||
// Check if this variant is marked `doc(hidden)`
|
||||
@ -648,12 +653,9 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
|
||||
.collect();
|
||||
|
||||
if hide_variant_show_wild {
|
||||
new.push(DeconstructedPat::wildcard(pcx.ty, pcx.span));
|
||||
new_patterns.push(DeconstructedPat::wildcard(pcx.ty, pcx.span));
|
||||
}
|
||||
|
||||
new
|
||||
};
|
||||
|
||||
witnesses
|
||||
.into_iter()
|
||||
.flat_map(|witness| {
|
||||
@ -669,6 +671,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
} else {
|
||||
witnesses
|
||||
.into_iter()
|
||||
|
@ -45,7 +45,8 @@ note: `E2` defined here
|
||||
|
|
||||
LL | pub enum E2 { A, B }
|
||||
| ^^^^^^^^^^^
|
||||
= note: the matched value is of type `E2`, which is marked as non-exhaustive
|
||||
= note: the matched value is of type `E2`
|
||||
= note: `E2` is marked as non-exhaustive
|
||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||
|
|
||||
LL | let _e = || { match e2 { E2::A => (), E2::B => (), _ => todo!() } };
|
||||
|
@ -45,7 +45,8 @@ note: `E2` defined here
|
||||
|
|
||||
LL | pub enum E2 { A, B }
|
||||
| ^^^^^^^^^^^
|
||||
= note: the matched value is of type `E2`, which is marked as non-exhaustive
|
||||
= note: the matched value is of type `E2`
|
||||
= note: `E2` is marked as non-exhaustive
|
||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||
|
|
||||
LL | match e2 { E2::A => (), E2::B => (), _ => todo!() };
|
||||
|
2
tests/ui/pattern/usefulness/auxiliary/non-exhaustive.rs
Normal file
2
tests/ui/pattern/usefulness/auxiliary/non-exhaustive.rs
Normal file
@ -0,0 +1,2 @@
|
||||
#[non_exhaustive]
|
||||
pub enum NonExhaustiveEnum { A, B }
|
18
tests/ui/pattern/usefulness/nested-non-exhaustive-enums.rs
Normal file
18
tests/ui/pattern/usefulness/nested-non-exhaustive-enums.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// aux-build:non-exhaustive.rs
|
||||
|
||||
extern crate non_exhaustive;
|
||||
|
||||
use non_exhaustive::NonExhaustiveEnum;
|
||||
|
||||
fn main() {
|
||||
match Some(NonExhaustiveEnum::A) {
|
||||
//~^ ERROR non-exhaustive patterns: `Some(_)` not covered [E0004]
|
||||
//~| NOTE pattern `Some(_)` not covered
|
||||
//~| NOTE `Option<NonExhaustiveEnum>` defined here
|
||||
//~| NOTE the matched value is of type `Option<NonExhaustiveEnum>`
|
||||
//~| NOTE `NonExhaustiveEnum` is marked as non-exhaustive
|
||||
Some(NonExhaustiveEnum::A) => {}
|
||||
Some(NonExhaustiveEnum::B) => {}
|
||||
None => {}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
|
||||
--> $DIR/nested-non-exhaustive-enums.rs:8:11
|
||||
|
|
||||
LL | match Some(NonExhaustiveEnum::A) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Some(_)` not covered
|
||||
|
|
||||
note: `Option<NonExhaustiveEnum>` defined here
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: not covered
|
||||
= note: the matched value is of type `Option<NonExhaustiveEnum>`
|
||||
= note: `NonExhaustiveEnum` is marked as non-exhaustive
|
||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||
|
|
||||
LL ~ None => {},
|
||||
LL + Some(_) => todo!()
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
@ -28,7 +28,8 @@ note: `NonExhaustiveEnum` defined here
|
||||
|
|
||||
LL | pub enum NonExhaustiveEnum {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive
|
||||
= note: the matched value is of type `NonExhaustiveEnum`
|
||||
= note: `NonExhaustiveEnum` is marked as non-exhaustive
|
||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||
|
|
||||
LL ~ NonExhaustiveEnum::Struct { .. } => "third",
|
||||
@ -46,7 +47,7 @@ note: `NonExhaustiveEnum` defined here
|
||||
|
|
||||
LL | pub enum NonExhaustiveEnum {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive
|
||||
= note: the matched value is of type `NonExhaustiveEnum`
|
||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||
|
|
||||
LL ~ match enum_unit {
|
||||
|
Loading…
Reference in New Issue
Block a user