pub struct Checker<T> { /* private fields */ }Expand description
Checks matches for exhaustiveness and usefulness, reusing its buffers from one check to the next.
check is a Checker used once with default limits. Keep
a Checker around when checking many matches (a whole program’s): after
the first few checks it allocates almost nothing. Configure it with:
with_step_limit: how much work one check may do before giving up withError::StepLimit.with_witness_limit: how many missing cases one report lists at most.
§Examples
use match_lang::{Arm, Checker, Model, Pat, Signature};
struct Bytes;
impl Model for Bytes {
type Ty = ();
fn signature(&self, _: &()) -> Signature<()> {
Signature::Int { min: 0, max: 255 }
}
fn fields(&self, _: &(), _: u32, _: &mut Vec<()>) {}
}
let mut checker = Checker::new().with_witness_limit(2);
for n in 0..10 {
let arms: Vec<Arm> = (0..n).map(|i| Arm::new(Pat::int(i * 2))).collect();
let report = checker.check(&Bytes, &(), &arms)?;
assert!(!report.is_exhaustive());
assert!(report.missing().len() <= 2);
}Implementations§
Source§impl<T: Clone> Checker<T>
impl<T: Clone> Checker<T>
Sourcepub fn new() -> Checker<T>
pub fn new() -> Checker<T>
A checker with the default limits (DEFAULT_STEP_LIMIT and
DEFAULT_WITNESS_LIMIT).
§Examples
use match_lang::{Checker, DEFAULT_STEP_LIMIT};
let checker: Checker<()> = Checker::new();
assert_eq!(checker.step_limit(), DEFAULT_STEP_LIMIT);Sourcepub fn with_step_limit(self, limit: u64) -> Checker<T>
pub fn with_step_limit(self, limit: u64) -> Checker<T>
Sets how many units of work one check may do. A unit is roughly one
matrix row, cell, or witness node built, or one constructor examined;
Report::steps tells how many a check used. A check that would
exceed the limit stops with Error::StepLimit, so time and memory
per check are bounded by the limit whatever the input.
§Examples
use match_lang::{Arm, Checker, Error, Model, Pat, Signature};
struct Bytes;
impl Model for Bytes {
type Ty = ();
fn signature(&self, _: &()) -> Signature<()> {
Signature::Int { min: 0, max: 255 }
}
fn fields(&self, _: &(), _: u32, _: &mut Vec<()>) {}
}
let arms: Vec<Arm> = (0..100).map(|i| Arm::new(Pat::int(i))).collect();
let mut tight = Checker::new().with_step_limit(10);
assert_eq!(tight.check(&Bytes, &(), &arms).unwrap_err(), Error::StepLimit { limit: 10 });Sourcepub fn with_witness_limit(self, limit: usize) -> Checker<T>
pub fn with_witness_limit(self, limit: usize) -> Checker<T>
Sets the most missing cases one report lists. At least one is always
kept, since the first witness is what proves a match non-exhaustive;
0 is treated as 1.
§Examples
use match_lang::Checker;
let checker: Checker<()> = Checker::new().with_witness_limit(0);
assert_eq!(checker.witness_limit(), 1);Sourcepub fn step_limit(&self) -> u64
pub fn step_limit(&self) -> u64
The step limit in effect.
§Examples
use match_lang::Checker;
assert_eq!(Checker::<()>::new().with_step_limit(99).step_limit(), 99);Sourcepub fn witness_limit(&self) -> usize
pub fn witness_limit(&self) -> usize
The witness limit in effect.
§Examples
use match_lang::{Checker, DEFAULT_WITNESS_LIMIT};
assert_eq!(Checker::<()>::new().witness_limit(), DEFAULT_WITNESS_LIMIT);Sourcepub fn check<M: Model<Ty = T>>(
&mut self,
model: &M,
ty: &T,
arms: &[Arm],
) -> Result<Report<T>, Error>
pub fn check<M: Model<Ty = T>>( &mut self, model: &M, ty: &T, arms: &[Arm], ) -> Result<Report<T>, Error>
Checks arms, in order, against values of type ty.
§Errors
Error::InvalidPatternif a pattern does not fit the type it is matched against (checked before any analysis).Error::StepLimitif the analysis needs more steps than the limit.Error::Modelif the model answers inconsistently.Error::TooLargepastu32::MAX - 1pattern nodes or matrix entries.
§Examples
use match_lang::{Arm, Checker, Model, Pat, Signature};
struct Flags;
impl Model for Flags {
type Ty = u8; // 0: (bool, bool), 1: bool
fn signature(&self, ty: &u8) -> Signature<u8> {
if *ty == 0 { Signature::Product } else { Signature::Bool }
}
fn fields(&self, _: &u8, _: u32, out: &mut Vec<u8>) {
out.extend([1, 1]);
}
}
let arms = [
Arm::new(Pat::product([Pat::bool(true), Pat::wild()])),
Arm::new(Pat::product([Pat::wild(), Pat::bool(true)])),
];
let report = Checker::new().check(&Flags, &0, &arms)?;
assert_eq!(report.missing()[0].to_string(), "(false, false)");