diff --git a/docs/BUGS-2026-09-18.md b/docs/BUGS-2026-09-18.md index fb24cc4..ed21ee6 100644 --- a/docs/BUGS-2026-09-18.md +++ b/docs/BUGS-2026-09-18.md @@ -107,6 +107,15 @@ territory; fix or record, the lane's call. rather than the arithmetic: `flan_f64_to_bytes` and the two dev emitters render any NaN as unsigned `nan`, which is what `format-f64` in the prelude always did. Pinned in `test/programs/format.flan`. See docs/BUILT.md. +- **x86's slice-from-ptr refusal is the wrong sentence**: `x86.ml` still reports a + negative promise through `flan_slice_error` — "slice [0 -2) is out of bounds for + length 0", naming a range and a length the caller never wrote — where `emit.ml` has + its own `flan_slice_promise_error`. Same condition and same exit on both sides, only + the text differs. The survey cannot see it: `bounds.flan` picks its case out of + `(at args 1)` and `survey.sh` runs every program with no arguments, so nothing in the + corpus reaches the `n = -2` case on the x86 path. Noticed while making the check + unconditional (which did not change what it prints); the fix is one `bounds_call` with + one extra instead of three. - **`emit.ml:3369` transient test ignores `new_globals`**: on the `retains=false` path a module first to intern a global gets dlclosed; zero-init makes it moot today, a literal init would dangle. diff --git a/spike/x86/p11-reversed-slice.flan b/spike/x86/p11-reversed-slice.flan new file mode 100644 index 0000000..d276d4e --- /dev/null +++ b/spike/x86/p11-reversed-slice.flan @@ -0,0 +1,26 @@ +;;;; A slice built backwards, for the survey rather than for a person. +;;;; +;;;; test/programs/bounds.flan already covers this, and cannot cover it here: +;;;; it picks its case out of (at args 1) and survey.sh runs every program +;;;; with no arguments at all. So the one backend comparison that would catch +;;;; check_slice's lo <= hi being re-gated on --no-bounds-checks is a program +;;;; that reaches the reversed slice on its own. +;;;; +;;;; What it pins is that both backends die here in *every* build. lo <= hi is +;;;; not a bounds check — it is the claim that the length word of the %slice +;;;; this expression builds is a count, and hi - lo is -1 — so +;;;; --no-bounds-checks has nothing here to drop, and running this sweep with +;;;; SURVEY_FLAGS=--no-bounds-checks must report the same MATCH as without it. +;;;; A backend that quietly builds the slice exits 0 while the other exits 134 +;;;; and the survey says DIFFER. +;;;; +;;;; The two ends come from (len args), which is 1 for a program run with no +;;;; arguments and is not a number either optimiser can see, so the branch +;;;; cannot be folded away and the checker has no literal to object to. +(defn main [args [string]] i32 + (let [s (bytes "hello") + hi (i32 (len args)) + lo (+ hi 1)] + (print (slice s lo hi)) + (println "")) + 0)