Skip to main content

Checker

Struct Checker 

Source
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:

§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>

Source

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);
Source

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 });
Source

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);
Source

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);
Source

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);
Source

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
§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)");

Trait Implementations§

Source§

impl<T> Debug for Checker<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Clone> Default for Checker<T>

Source§

fn default() -> Checker<T>

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<T> Freeze for Checker<T>
where Engine<T>: Freeze,

§

impl<T> RefUnwindSafe for Checker<T>
where Engine<T>: RefUnwindSafe,

§

impl<T> Send for Checker<T>
where Engine<T>: Send,

§

impl<T> Sync for Checker<T>
where Engine<T>: Sync,

§

impl<T> Unpin for Checker<T>
where Engine<T>: Unpin,

§

impl<T> UnsafeUnpin for Checker<T>
where Engine<T>: UnsafeUnpin,

§

impl<T> UnwindSafe for Checker<T>
where Engine<T>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.