A Rust-like ownership system with simpler call-site syntax, taped onto a Python-shaped surface, sitting on MLIR, headed to open source in fall 2026.
§1 Provenance
- Vendor: Modular Inc. Lead: Chris Lattner.
- Reference docs: https://docs.modular.com/mojo/manual/values/ownership/ . Deep dive: https://www.modular.com/blog/deep-dive-into-ownership-in-mojo .
- Lifetimes / provenance proposal: https://github.com/modular/modular/discussions/338 .
- Wikipedia summary: https://en.wikipedia.org/wiki/Mojo_(programming_language) .
- Production-ready milestone: Q1 2026.
- Open source commitment: “fall 2026” for the compiler; the standard library has been open since 2024.
- 2024–2025 contributor: Evan Ovadia (Vale) worked at Modular Jul 2024 – Dec 2025 on linear types, associated aliases, struct extensions, and CPU/GPU boundary type-checking.
§2 Core type discipline
Mojo bakes single-owner discipline into argument conventions, not types. The three keywords are:
read(wasborrowedpre-2024): immutable borrow, callee may read, not mutate.mut(wasinout): mutable borrow, callee reads and writes the caller’s storage.var(wasowned): callee takes ownership; caller’s binding is dead after the call.
Defaults:
fn-defined functions default arguments toread(Mojo’s safe surface).def-defined functions default arguments tovar(Python-compat surface; copies are made for caller-isolation).
Transfer operator: f(a^) explicitly moves a into f, regardless of the parameter convention. The compiler will perform this implicitly when it sees the call is the last use of a (NRVO-style).
Judgement form: a flow-sensitive last-use analysis across MIR-equivalent. The borrow checker tracks:
- Aliasing-XOR-mutation per stack slot.
- Move-after-use forbidden.
- Lifetime / provenance parameters on references that escape (the active “lifetimes & provenance” RFC formalises these as second-class capability-style markers, not full Rust regions).
Principal example: the Mojo read/mut/var triple lets a numerics function read its inputs without copying tensors and mutate an output in place:
fn matmul(read a: Tensor, read b: Tensor, mut out: Tensor): ...The caller writes matmul(a, b, out) with no & sigil. The borrow checker proves a, b, out are disjoint.
§3 Memory-safety invariant
Same as Rust: aliasing-XOR-mutation, no UAF, no double-free, no data race on memory. Mojo additionally claims Python-interop without aliasing leaks: when a Python object enters Mojo it is wrapped in PythonObject, which is RC’d, opting out of the borrow checker for that subgraph.
§4 Compiler implementation cost
- Built on MLIR, not bare LLVM. Borrow checking is one of several MLIR dialects/passes.
- Lattner has stated the borrow checker took less code than Rust’s because lifetimes are second-class (parameters cannot be parameterised over lifetimes the way Rust’s
<'a>does), so the inference engine is simpler. - Diagnostics: better than early Rust because the team learned from a decade of Rust’s mistakes; you get suggestions like “did you mean to write
f(a^)?” automatically. - The compiler is closed source as of May 2026; commitment to open source is fall 2026. Until then, third-party verification of the soundness claims is limited.
§5 Production / language adoption status (May 2026)
- Modular ships Mojo inside its MAX AI runtime; the production-ready Mojo release is Q1 2026.
- Standard library is open; compiler closes for now.
- Major adopters: Modular’s own kernels (matmul, attention), Lambda Labs and a handful of HPC shops experimenting.
- Mojo is the only post-Rust language that pairs a borrow checker with first-class GPU/TPU codegen. That, plus the Python surface, is the differentiator.
§6 Mochi adaptation note
Mojo’s design choice is the most directly relevant to Mochi: borrow conventions on parameters, no lifetime variables, no & sigil at call site. That is exactly the shape MEP-41 should target.
Smallest surface-language change MEP-41 could lift verbatim:
fun fill(read src: list<int>, mut dst: list<int>) { ... }read(alias for current implicit default): documentation only, no extra check.mut: type checker rejects the call if the caller’s argument expression is not assignable, and warns if twomutarguments alias.var: caller’s binding is removed from scope after the call; only legal in avar(mutable) binding context.
The transfer operator f(a^) is too cryptic for Mochi’s style; instead, an explicit consume a statement before the call (or built-in f(consume a)) is more readable.
vm3 tie-in: a var parameter conceptually moves a handle Cell. The runtime does nothing different — handle is copied, then source slot is set to null. Optionally, the gen on the moved-from slot is bumped, giving any leftover handle a fast UAF trap.
Effects (MEP-15) tie-in: a mut parameter is an effect on the caller’s storage. MEP-15 could grow a local effect (writes to caller-visible bindings) and propagate it, completing the symmetry with io/fs/net.
Options (MEP-16) tie-in: var over an Option<T> plus a static check that the source is Some gives a panic-free take. This is the exact Swift Optional.take() idiom (SE-0437).
Incompatible pieces:
- Mojo’s lifetimes / provenance system. Mochi has GC + generations; there is no need for static lifetime parameters.
- The
^transfer operator (visual noise that does not fit Mochi’s surface). - Python interop. Mochi’s FFI is into Go, not Python; the analogous problem (a Go pointer that outlives a Cell) is different.
§7 Open questions for MEP-41
- Does Mochi want a
def/fnsplit wheredefis permissive (auto-copy) andfnenforces the borrow conventions? This buys gradual adoption. - Should
mutpropagate to closure captures the way Mojo’s does? - Can MEP-41’s
varconvention be implemented as a bytecode transform (zero source slot on call) without touching the type checker? - Mojo defers full lifetime tracking to a future provenance system. Does MEP-41 want to defer the same way, or commit to vm3’s gen-check as the permanent answer?
Sources: https://docs.modular.com/mojo/manual/values/ownership/ ; https://www.modular.com/blog/deep-dive-into-ownership-in-mojo ; https://github.com/modular/modular/discussions/338 ; https://en.wikipedia.org/wiki/Mojo_(programming_language) .