Pacts
mimas is built for embedded use, so Rust’s full trait machinery — generics, associated types, blanket impls, and the constraint solver behind them — is intentionally out of scope. Even so, abstracting over types is sometimes genuinely useful: without any way to do it, every function that wants to handle “anything with this behavior” has to be rewritten per concrete type.
It comes up most at the FFI line. A host project large enough to span several crates often leans on traits at its boundaries, and a mimas script needs some way to interoperate with at least the simplest of those patterns.
A pact fills that role. It’s a named set of method, associated-function, and constant signatures — a contract a type satisfies by writing impl PactName for TheType { ... } and supplying the listed items. Anywhere a type is expected, a pact can stand in, and the checker will accept any value whose type fulfills it.
pact Draw {
fn draw(self);
}
struct Square;
impl Draw for Square {
fn draw(self) { /* draw a square */ }
}
struct Circle;
impl Draw for Circle {
fn draw(self) { /* draw a circle */ }
}
fn render_all(items: [Draw]) {
for item in items {
item.draw();
}
}
Constants
A pact can require constants as well as methods.
pact Named {
const NAME: str;
}
impl Named for Square {
const NAME = "Square";
}
let n = Square::NAME; // "Square"
Default implementations
A pact item can ship with a default, which an implementer may use as-is or override.
pact Identified {
const ID: int;
fn describe() {
print(f"my id is {Self::ID}");
}
}
impl Identified for Square {
const ID = 0;
// `describe` is inherited
}
Square::describe(); // "my id is 0"
Reaching pact items through a value
Without generics, mimas can’t lean on Rust’s T::ITEM syntax to read an associated item off a constrained type. This is why dot access reaches associated items — given a value known only by its pact, you still need a way to get at its constants and methods, and . is it.
fn announce(thing: Identified) {
let id = thing.ID;
thing.describe();
}
Binding multiple pacts
An annotation can require several pacts at once with +:
struct Widget {
item: Named + Identified,
}
To make a multi-pact bound optional or a result, wrap it in parentheses first so the ?/! applies to the whole thing:
struct Widget {
item: (Named + Identified)?,
}