bounds.flan covers this already and the x86 survey cannot see it: the
program picks its case out of (at args 1) and survey.sh runs everything
with no arguments, so re-gating x86's lo <= hi would have failed
nothing. This probe reaches the reversed slice on its own, through
(len args) so that neither optimiser can fold the branch and the checker
has no literal to object to. It matches under the default sweep and
under SURVEY_FLAGS=--no-bounds-checks, which is the claim.
Also records what the same reading turned up and did not fix: x86 still
reports a negative slice-from-ptr promise through flan_slice_error, so
the two backends print different sentences for it, and no corpus program
reaches that case without arguments.
(/ 0.0 0.0) printed nan through LLVM, which folds it at compile time to
the positive quiet NaN, and -nan through x86, where divsd computes the
negative one. Put the operands in globals so nothing folds and both say
-nan, so the divergence is the folding path and not the arithmetic.
The sign bit of a NaN is not a property of the number and IEEE 754 does
not specify it, so the print site is where this is answered.
flan_f64_to_bytes renders any NaN as nan, and the two dev emitters do
the same. That is not a new rule: format-f64 in the prelude has always
answered nan for this value, so a build where (print x) said -nan and
(show x 2) said nan was contradicting itself inside one backend. An
infinity still prints signed.
format.flan prints the three non-finite values through print as well as
through show. It is in the survey corpus, so the one program pins the
printed form under dune test and the agreement between backends under
the survey.
The lo <= hi test in check_slice and slice-from-ptr's n >= 0 sat behind
--no-bounds-checks in both backends, while the comment beside each said
they could not be dropped. They are not bounds checks: hi <= len asks
whether a range fits inside a length, and lo <= hi asks whether the word
about to be written into a %slice's length field is a count at all. The
first stays behind the flag, the second is now emitted everywhere, the
way flan_vec_as_slice has always validated its own l > h in plain C.
emit.ml emits two signal blocks rather than one and i1, so an unchecked
build carries one compare. x86.ml keeps all three frame temporaries
stored outside the flag and gates only the second compare, because the
third is the length the message prints.
The IR assertion in test_acceptance now says the two slice calls are
present under --no-bounds-checks rather than absent, and the same build
is run: case 2 and case -2 of bounds.flan must still die.