Skip to content

Typechecker normalization of type-level expressions #48

@iljakuklic

Description

@iljakuklic

Background

The typechecker currently performs NbE evaluation only for type-level computation (comparing types in val_eq, instantiating dependent Pi closures). It does not normalize arithmetic expressions in terms — those remain as App(Prim::Add, ...) nodes in the core IR and are only reduced by the staging evaluator.

This is fine for the current prototype, but will become load-bearing once dependent types are in use. Consider a type like:

Vec(u32, n + 1)

The typechecker needs to be able to normalize n + 1 (and reason about its relationship to other size expressions) in order to typecheck programs that use Vec.

The wrapping semantics question

The meta-evaluator now uses wrapping arithmetic (matching Wasm's i32/i64) for phase coherence between fn and code fn. However, wrapping semantics are a poor fit for size indices: Vec(u32, 255 + 1) silently producing a 0-element vector would be surprising and unsafe.

This suggests that size indices may want a separate integer type — perhaps an unbounded Nat, or a large fixed-width type treated as a proof-irrelevant index — with distinct (non-wrapping, or checked) arithmetic semantics. This is a common pattern in dependently-typed languages (Agda's , Idris's Nat).

Open questions

  • Should size indices use a dedicated Nat-like type, or a fixed-width integer with non-wrapping semantics?
  • If a separate type, how does it relate to object-level integer types? (Lifting, coercions, bounded proofs?)
  • How does normalization interact with the existing NbE evaluator — does size arithmetic share the same evaluator, or get a separate reduction strategy?
  • What normal forms are needed for the typechecker to decide type equality of expressions like Vec(A, m + n) vs Vec(A, n + m)?

Relationship to phase polymorphism

With phase polymorphism, a function quantifying over a size n : ??? and returning Vec(A, n) needs the size type to be well-behaved at both meta and object phase. This further constrains the design.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions