marianoguerra/wax/check/store does not have a README file

    RecType

    type RecType[Idx] = Array[SubType[Idx]]

    A rec group: the types defined together, which may therefore refer to each other.

    MalformedRecGroup

    type MalformedRecGroup derive(Eq,
    Debug
    )

    A rec group that is not well-formed.

    The reference raises Invalid_argument here. It is a backstop rather than a user-facing diagnostic: a violation means the caller mis-normalized the group, which is the source-versus-canonical index confusion class, and is rejected rather than left to silently corrupt the subtyping relation.

    FuncType

    A function type.
    pub struct Id {
    index : Int
    } derive(Eq, Hash,
    Debug
    )

    The canonical index of a type: what add_rectype returns and get_subtype requires.

    Deliberately opaque -- no of_int, no to_int -- so that outside this module an Id can only come from the store, and can never be fabricated from, or confused with, a source-level or wire-level integer. The reference makes exactly the same choice, and for exactly the same reason: the source-versus-canonical index confusion is the bug class this prevents.

    Id::add

    fn Id::add(self : Id, n : Int) -> Id

    The canonical index n positions after this one -- e.g. the n-th member of a rec group whose first member is this.

    Id::of_index

    fn Id::of_index(index : Int) -> Id

    The canonical index a code generator refers to a type by.

    The store hands indices out in order from zero, so an index and an Id are the same number seen from two sides -- but only this package may say so, and only for a consumer that already works in indices because the binary format does. Everything else must treat Id as opaque, which is what keeps the interning honest.

    Id::to_int_for_tests_only

    fn Id::to_int_for_tests_only(self : Id) -> Int

    The underlying integer, for tests that render an index. Not for production code, which must treat Id as opaque.

    RefIndex

    pub(all) enum RefIndex {
    Def(Id)
    Rec(Int)
    } derive(Eq, Hash,
    Debug
    )

    A reference inside a rec group being registered.

    Def denotes an already-defined type by its canonical index; Rec denotes the group's own pos-th member. Two constructors rather than one integer space with a sign bit, so the two cannot be confused and an Id is only ever a genuine store index.

    SubType

    pub(all) struct SubType[Idx] {
    final_ : Bool
    supertype : Idx?
    descriptor : Idx?
    describes : Idx?
    typ : CompType[Idx]
    } derive(Eq, Hash,
    Debug
    )

    A defined type: what it defines, whether it may be subtyped further, and the one supertype it declares.

    descriptor and describes are the custom-descriptors proposal's two clauses -- the type of this struct's runtime descriptor, and the struct this one is the descriptor of. They are part of the type's IDENTITY, so they are here and not alongside: two structs with the same fields but different descriptors are different types, and interning has to see the difference.

    The reference DIVERGES here, and knowingly: its subtype_eq discards both clauses, so two otherwise identical structs dedup whatever their descriptors -- but its hash is a truncated structural one that may still separate them, which leaves the outcome depending on where the truncation falls. Rather than reproduce a hash-dependent answer we take the proposal's, which is also the one the two clauses are for. If a corpus file ever turns this into a byte difference it will show as a type-section drift, and this is the note that explains it.

    SubType::map

    fn[A, B] SubType::map(self : SubType[A], f : (A) -> B) -> SubType[B]

    Map every type reference in a defined type. The reference needs a functor application for this; here it is a function.

    SubtypingInfo

    pub struct SubtypingInfo {
    subtypes : Array[SubType[Id]]
    }

    Everything needed to answer subtyping questions: every defined type, in canonical index order, fully resolved.

    SubtypingInfo::get_subtype

    fn SubtypingInfo::get_subtype(self : SubtypingInfo, id : Id) -> SubType[Id]

    TypeStore

    pub struct TypeStore {
    interned : Map[Array[SubType[RefIndex]], Int]
    last_index : Int
    groups : Array[(Int, Array[SubType[RefIndex]])]
    }

    A context holding recursive type definitions.

    TypeStore::add_rectype

    fn TypeStore::add_rectype(self : TypeStore, group : Array[SubType[RefIndex]]) -> Id raise MalformedRecGroup

    Register a rec group, returning the canonical index of its first member.

    A structurally equal group already in the store is not added again: its existing index is returned, which is what makes two spellings of the same recursive type the same type.

    TypeStore::get_all_rectypes

    fn TypeStore::get_all_rectypes(self : TypeStore) -> Array[Array[SubType[Id]]]

    Every rec group in the store, resolved, in the order they were registered.

    TypeStore::last_index

    fn TypeStore::last_index(self : TypeStore) -> Int

    The index the next freshly added type would receive, i.e. how many types are currently defined.

    TypeStore::new

    fn TypeStore::new() -> TypeStore

    TypeStore::subtyping_info

    fn TypeStore::subtyping_info(self : TypeStore) -> SubtypingInfo

    Resolve the whole store.

    The reference memoises this on the context and invalidates it whenever a type is added, because a query must see the current type space. The cache belongs to the checker's type_context rather than here; this stays a pure function of the store.

    heap_subtype

    Is ty a subtype of ty'?

    Matched supertype first, then subtype. The reference writes both arms exhaustively and without a wildcard row so that a new heap type forces every relevant arm to be revisited; the same discipline is kept here, which is why this is long rather than clever.

    An Exact i reference has the same proper supertypes as i (since exact i <: i), so on the left it follows the Type i rules -- but among concrete types exact is invariant, so on the right only the same exact type matches. The bottom heap types are subtypes of the exact types too.

    ref_subtype

    A non-nullable reference is a subtype of a nullable one, never the reverse.

    val_subtype

    Subtyping is only interesting between references; every other value type is a subtype of itself alone.

    Source Files

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io