When Two Concepts Are One: Region and Arena

The five-strategy design space had both an 'arena' and a 'region', and they looked suspiciously alike. On inspection they were the same idea under two names — bump-allocate, free the whole area at once — dressed up with different incidental features. Collapsing them into a single concept, and why removing a false distinction early keeps everything downstream coherent.

merememory-modelregionslanguage-designsimplification

The previous episode ended on a suspicion: the design space had both an arena and a region, and they looked far too much alike. This episode is about following that suspicion to its conclusion — that they were one concept wearing two names — and deciding to keep only one.

Two descriptions, one idea

Written out side by side, the two were describing the same machinery.

The arena: bump-pointer allocation, no individual frees, everything released at once when the arena is torn down; cross-references inside a single arena are free, which makes it excellent for graphs; and only cleanup-free types are allowed in it.

The region: a memory area tied to program structure, scoped to a block, nestable, released in bulk when the block exits.

Line those up and the “difference” evaporates. Bump-allocate, don’t free individually, free the whole area on scope exit, share freely within is the textbook description of a region in the Tofte–Talpin sense — the well-studied region calculus that ML-family languages borrowed from. The arena, as described, was that same calculus under a different name.

The apparent distinctions were incidental, not fundamental:

  • Nesting was documented for regions and merely unmentioned for arenas — not forbidden, just unwritten.
  • The “only cleanup-free types allowed” constraint was spelled out for arenas and left implicit for regions — but a region needs the exact same rule, for the exact same reason.
  • Each had picked up a slightly different bit of syntax, which made two names feel like two things.

None of that is a real difference in what the feature is. It was two sketches of one idea that had drifted apart because they were written at different times.

The decision: one concept, called region

So the two were collapsed into a single feature, keeping the union of their useful parts: a scoped, nestable area, allocated by bumping a pointer, freed all at once when its block ends, with free cross-references inside it — and one rule about what may live in it (the subject of the next episode). It is written the obvious way:

region r {
  // allocate into r; everything here is freed when the block ends
}

The name kept is region, not arena. Partly because it names the established theory the design is standing on, and partly because — as a later episode on naming will get to — “region” turns out to be load-bearing in the language’s own identity.

Why bother collapsing early

This looks like tidying, but it was one of the higher-leverage decisions in the whole memory model, for a reason the design notes stated bluntly: almost every other memory decision depends on this one. View types, the region-aware standard collections, the order in which cleanup runs — each of those is an argument about “how do regions behave?” If there were still two overlapping concepts, every one of those arguments would have to be made twice, once per concept, and kept in sync forever. A false distinction is not free; it is a tax paid on every future decision.

Collapsing it up front meant the rest of Part II could reason about one thing.

There is also a straight line back to the first principle of the language. Mere optimizes for programs you can read and be sure of — and two names for one idea works directly against that. A reader would have to learn the difference (there isn’t one), decide which to use (it doesn’t matter), and hold both in their head (wasted). Fewer concepts, each meaning exactly one thing, is the same goal as explicit types and explicit effects, just applied to the vocabulary of the language itself. Simplicity here is not aesthetics; it is verifiability.

What this opened up

Unifying to a single region immediately sharpened the questions that had been fuzzy while there were two:

  • What is actually allowed to live in a region? Bump-allocate-and-bulk-free works only for values that don’t need real cleanup. A value holding a file handle or a socket can’t be freed by resetting a pointer. That constraint has a name — Trivial — and the separate story for values that do need cleanup is the next episode.
  • What does a reference into a region mean, and how do we stop it from outliving the region? That becomes its own small theory, a couple of episodes on.

One concept, sharp edges. Next: Trivial, and how Mere handles the values a region deliberately can’t.

← Back to Mere: Building a Language