flan/test/programs/map-stale-region.flan
Joseph Ferano c45447a6d4 The Map's tests join the suite, and the epoch trap covers its half
maps.flan and map-exhausted.flan as fixed-output cases, the six refusals
by name, and map-stale-region.flan beside stale-region.flan.

The last one is not a line in the Vec's program because the two reach
the check by different routes. A Vec's operations check on the way in
and stop there. A map's get goes on to call a hash and an equality
function through pointers into the block, so a missing check there is
not a wrong number — it is a probe loop walking released memory. It
traps naming the site and exits 134, as the Vec's does.

{K V} resolves now, so the test that asserted it was milestone 6 is
replaced by the one that still holds: the arity, refused for the reason
Vec's arity is refused, because a near-miss would otherwise resolve to a
type variable and come back as generics.
2026-09-12 16:09:27 +07:00

26 lines
1.2 KiB
Plaintext

;;;; spec-memory.md, "Dev builds detect a released region" — the Map's half.
;;;;
;;;; A Map records the epoch of the allocator it was made with, exactly as a
;;;; Vec does, and free-all bumps that counter. Any operation on a container
;;;; whose recorded epoch has moved traps, naming the site.
;;;;
;;;; This is worth its own program rather than a line in stale-region.flan
;;;; because the two containers reach the check by different routes: a Vec's
;;;; every operation takes the Vec's address and checks on the way in, while a
;;;; map's get goes on to call a hash and an equality function through pointers
;;;; into a block that is no longer there. If the check were missing here, the
;;;; failure would not be a wrong number — it would be a probe loop walking
;;;; released memory.
(defn main [] i32
(let [a (arena-new 65536)]
(let [m (map-new i32 i32 a)]
(put m 1 10)
(put m 2 20)
(match (get m 2) (Some v) (println v) None (println "missing"))
;; The region goes. m is still in scope and still looks fine — nothing is
;; released at scope exit and nothing marked m — which is exactly the
;; case a static rule cannot see.
(free-all a)
(match (get m 2) (Some v) (println v) None (println "missing"))))
0)