rust/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
Nicholas Nethercote b023671ce2 Add pattern_complexity_limit to Limits.
It's similar to the other limits, e.g. obtained via `get_limit`. So it
makes sense to handle it consistently with the other limits. We now use
`Limit`/`usize` in most places instead of `Option<usize>`, so we use
`Limit::new(usize::MAX)`/`usize::MAX` to emulate how `None` used to work.

The commit also adds `Limit::unlimited`.
2025-02-17 09:30:33 +11:00

91 lines
2.2 KiB
Rust

//! Test exhaustiveness checking.
use common::*;
use rustc_pattern_analysis::MatchArm;
use rustc_pattern_analysis::pat::{DeconstructedPat, WitnessPat};
use rustc_pattern_analysis::usefulness::PlaceValidity;
#[macro_use]
mod common;
/// Analyze a match made of these patterns.
fn check(patterns: Vec<DeconstructedPat<Cx>>) -> Vec<WitnessPat<Cx>> {
let ty = *patterns[0].ty();
let arms: Vec<_> =
patterns.iter().map(|pat| MatchArm { pat, has_guard: false, arm_data: () }).collect();
let report =
compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, usize::MAX)
.unwrap();
report.non_exhaustiveness_witnesses
}
#[track_caller]
fn assert_exhaustive(patterns: Vec<DeconstructedPat<Cx>>) {
let witnesses = check(patterns);
if !witnesses.is_empty() {
panic!("non-exhaustive match: missing {witnesses:?}");
}
}
#[track_caller]
fn assert_non_exhaustive(patterns: Vec<DeconstructedPat<Cx>>) {
let witnesses = check(patterns);
assert!(!witnesses.is_empty())
}
#[test]
fn test_int_ranges() {
let ty = Ty::U8;
assert_exhaustive(pats!(ty;
0..=255,
));
assert_exhaustive(pats!(ty;
0..,
));
assert_non_exhaustive(pats!(ty;
0..255,
));
assert_exhaustive(pats!(ty;
0..255,
255,
));
assert_exhaustive(pats!(ty;
..10,
10..
));
}
#[test]
fn test_nested() {
let ty = Ty::BigStruct { arity: 2, ty: &Ty::BigEnum { arity: 2, ty: &Ty::Bool } };
assert_non_exhaustive(pats!(ty;
Struct(Variant.0, _),
));
assert_exhaustive(pats!(ty;
Struct(Variant.0, _),
Struct(Variant.1, _),
));
assert_non_exhaustive(pats!(ty;
Struct(Variant.0, _),
Struct(_, Variant.0),
));
assert_exhaustive(pats!(ty;
Struct(Variant.0, _),
Struct(_, Variant.0),
Struct(Variant.1, Variant.1),
));
}
#[test]
fn test_empty() {
// `TY = Result<bool, !>`
const TY: Ty = Ty::Enum(&[Ty::Bool, Ty::Enum(&[])]);
assert_exhaustive(pats!(TY;
Variant.0,
));
let ty = Ty::Tuple(&[Ty::Bool, TY]);
assert_exhaustive(pats!(ty;
(true, Variant.0),
(false, Variant.0),
));
}