Automatic boxing
Zena has no automatic boxing. A primitive is never silently wrapped in a heap
object to make it fit somewhere a reference is expected. Where a boxed primitive
is needed, Box<T> is written explicitly:
let x: Box<i32> = new Box(42); // the allocation is visible
Why it is rejected ​
Boxing is an allocation. Zena's rule is that an allocation is visible in the source that causes it, and automatic boxing breaks that rule in the worst place: inside loops, per element, in code that reads as if it does nothing.
The rule is not an isolated preference. Three other decisions exist to enforce it:
- Unions cannot mix primitives with references,
so
i32 | Stringis rejected rather than boxed. - Generics are reified, so
Array<i32>holds unboxedi32rather than boxed elements. - Multi-value returns exist so that
an optional result does not need an allocated
Option.
Automatic boxing would have undone all three.
No any ​
Zena has no any type. A type that accepts every value has to do one of two
things, and neither is acceptable:
- Waive type checking, as TypeScript's
anydoes. Zena's type system is sound: a program that type-checks has correct types at runtime. A construct that opts out of checking gives that up wherever it appears. - Box primitives so they fit alongside references. That is the allocation this page exists to rule out.
A checked any — one that requires an explicit cast before use — solves the
first problem and not the second. It still allocates on let x: any = 42, with
nothing in the line to say so.
anyref is a different type ​
anyref is the top type for reference types. Every class, array, and closure
is an anyref; no primitive is.
let r: anyref = someObject; // no allocation — already a reference
let n: anyref = 42; // error
It is the version of "could be anything" that costs nothing, and it covers the
case an any type would be reached for.
→ Working documents:
primitive-boxing-semantic-types.md,
polymorphic-references.md