pub trait Model {
type Ty: Clone;
// Required methods
fn signature(&self, ty: &Self::Ty) -> Signature<Self::Ty>;
fn fields(&self, ty: &Self::Ty, variant: u32, out: &mut Vec<Self::Ty>);
// Provided methods
fn is_empty(&self, ty: &Self::Ty) -> bool { ... }
fn variant_name(&self, ty: &Self::Ty, variant: u32) -> Option<&str> { ... }
}Expand description
A language’s constructor model.
The checker never sees the language’s types directly. It asks the model
two questions about a type: what its Signature is (which constructors
build its values), and what the field types of a constructor are. That is
enough to decide exhaustiveness and usefulness for every type the
signatures can describe: sums, products, booleans, bounded and unbounded
integers, characters, opaque literals, arrays, and slices.
The model must answer consistently: the same type must get the same
signature and fields every time during one check. A model that changes
its answers mid-check is reported as Error::Model,
never a panic.
Ty is whatever names a type in the language: an interned id is ideal,
since the checker clones types as it descends into fields.
§Examples
A model for bool and Option<T>:
use match_lang::{Model, Signature};
#[derive(Clone)]
enum Ty {
Bool,
Option(Box<Ty>),
}
struct Lang;
impl Model for Lang {
type Ty = Ty;
fn signature(&self, ty: &Ty) -> Signature<Ty> {
match ty {
Ty::Bool => Signature::Bool,
Ty::Option(_) => Signature::Sum { count: 2 },
}
}
fn fields(&self, ty: &Ty, variant: u32, out: &mut Vec<Ty>) {
// `None` (variant 0) has no fields; `Some` (variant 1) has one.
if let (Ty::Option(inner), 1) = (ty, variant) {
out.push((**inner).clone());
}
}
fn variant_name(&self, ty: &Ty, variant: u32) -> Option<&str> {
match (ty, variant) {
(Ty::Option(_), 0) => Some("None"),
(Ty::Option(_), 1) => Some("Some"),
_ => None,
}
}
}
let mut fields = Vec::new();
Lang.fields(&Ty::Option(Box::new(Ty::Bool)), 1, &mut fields);
assert!(matches!(fields[..], [Ty::Bool]));Required Associated Types§
Required Methods§
Sourcefn signature(&self, ty: &Self::Ty) -> Signature<Self::Ty>
fn signature(&self, ty: &Self::Ty) -> Signature<Self::Ty>
The constructors that build values of ty.
§Examples
use match_lang::{Model, 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<()>) {}
}
assert_eq!(Bytes.signature(&()), Signature::Int { min: 0, max: 255 });Sourcefn fields(&self, ty: &Self::Ty, variant: u32, out: &mut Vec<Self::Ty>)
fn fields(&self, ty: &Self::Ty, variant: u32, out: &mut Vec<Self::Ty>)
Pushes onto out the field types of a constructor of ty, in field
order: variant variant of a Sum, or the single
constructor of a Product (variant is then
0). out is empty when called. It is not called for other
signatures: booleans, integers, characters, and opaque literals have
no fields, and arrays and slices name their element type in the
signature.
§Examples
use match_lang::{Model, Signature};
// A model of `(bool, bool)`: the unit type `()` stands for `bool`
// inside, and `None` for the pair.
struct Pair;
impl Model for Pair {
type Ty = Option<()>;
fn signature(&self, ty: &Option<()>) -> Signature<Option<()>> {
match ty {
None => Signature::Product,
Some(()) => Signature::Bool,
}
}
fn fields(&self, _: &Option<()>, _: u32, out: &mut Vec<Option<()>>) {
out.extend([Some(()), Some(())]);
}
}
let mut out = Vec::new();
Pair.fields(&None, 0, &mut out);
assert_eq!(out.len(), 2);Provided Methods§
Sourcefn is_empty(&self, ty: &Self::Ty) -> bool
fn is_empty(&self, ty: &Self::Ty) -> bool
Whether ty has no values at all, like ! or an enum with no
variants.
The checker treats a constructor as impossible when one of its fields
is empty, so Err(_) is not required, and is reported unreachable,
for a Result<T, !>. For that to be exact the answer should be deep:
a tuple or struct with an empty field is itself empty. The default
recognizes only Sum { count: 0 }.
§Examples
use match_lang::{Model, Signature};
struct Never;
impl Model for Never {
type Ty = ();
fn signature(&self, _: &()) -> Signature<()> {
Signature::Sum { count: 0 }
}
fn fields(&self, _: &(), _: u32, _: &mut Vec<()>) {}
}
assert!(Never.is_empty(&()));Sourcefn variant_name(&self, ty: &Self::Ty, variant: u32) -> Option<&str>
fn variant_name(&self, ty: &Self::Ty, variant: u32) -> Option<&str>
A name for variant variant of ty (or, with variant 0, for a
product type), used only when printing witnesses with
Witness::display. Without a name a
variant prints as #index and a product as a tuple.
§Examples
use match_lang::{Model, Signature};
struct Unit;
impl Model for Unit {
type Ty = ();
fn signature(&self, _: &()) -> Signature<()> {
Signature::Product
}
fn fields(&self, _: &(), _: u32, _: &mut Vec<()>) {}
}
assert_eq!(Unit.variant_name(&(), 0), None);Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".