Skip to content

Scheme: haskell-show-float mangles large/edge values (e.g. 4000000001 → "1..e-8"); run-tests.sh masks the failure with exit 0 #447

@joshsh

Description

@joshsh

Summary

The Scheme head's haskell-show-float (hand-written runtime in
heads/lisp/scheme/src/main/scheme/hydra/lib/literals.scm) produces malformed
output for at least one value that takes the scientific-notation branch: a test
expecting 4000000001 gets 1..e-8 (note the double dot — malformed). One scheme
target test fails (2571 passed, 1 failed, 7 skipped).

A second, compounding issue: packages/hydra-lisp/bin/run-tests.sh scheme exits 0
despite the failed assertion
, so CI's "Scheme tests" job (and prepare-release.sh's
Lisp step) report success. This failure is therefore CI-invisible and has likely been
latent on main for a while — it only surfaced when reading the test output during
0.16.0 release prep.

Root cause (float formatter)

haskell-show-float (literals.scm:317) routes |x| < 0.1 or |x| >= 1.0e7
through a scientific-notation branch (literals.scm:323). That branch's
string-manipulation path was written for small decimals — it assumes the
number->string output looks like "0.0...digits" and does
after-dot = (substring digits 2 ...) (literals.scm:338), i.e. it strips a literal
"0." prefix. For a large value (>= 1e7), number->string returns something like
"4000000001.0" or "4.000000001e9", so the substring digits 2 assumption is wrong
and the mantissa/exponent reconstruction yields the malformed 1..e-8.

The small-decimal path and the large-value path need to be handled separately (or the
formatter should reuse a single correct mantissa/exponent computation rather than
string-slicing that assumes a "0." prefix). The target is parity with Haskell's
Show instance (scientific for |x| < 0.1 or |x| >= 1e7, decimal otherwise, full
precision) — see the haskell-show-float32 sibling (literals.scm:361) which computes
exponent via log/floor instead of string-slicing and may be the better model.

Harness bug (failure masking)

packages/hydra-lisp/bin/run-tests.sh scheme exits 0 with a failed assertion present
(reproduced: direct re-run prints 2571 passed, 1 failed yet $? == 0). Because CI and
prepare-release.sh key off the exit code, scheme failures are silently green. This
should be fixed independently so scheme failures actually gate going forward (the other
Lisp dialects should be checked for the same behavior).

Reproduction

packages/hydra-lisp/bin/run-tests.sh scheme   # prints "2571 passed, 1 failed"; exit 0
# failing assertion:  Expected: 4000000001   Actual: 1..e-8

Notes / scope

  • Hand-written Scheme runtime; the float formatter, not generated code.
  • Not introduced by the 0.16.0 cycle (literals.scm float code last changed 2026-06-06,
    before the last green main CI); surfaced now because scheme isn't in the triad
    bootstrap//test and was only exercised by prepare-release.sh's Lisp step.
  • Not a 0.16.0 release gate (Lisp is a quality check per prepare-release.sh; the
    released set — Haskell/Java/Python — is fully green). Tracking as a post-0.16.0
    follow-up unless prioritized.

Suggested tasks

  • Fix haskell-show-float large-value (>= 1e7) scientific-notation path in
    literals.scm (consider unifying with the haskell-show-float32 exponent approach).
  • Add/keep a regression test covering large-magnitude and boundary float formatting.
  • Make run-tests.sh propagate a non-zero exit on any failed assertion (scheme; audit
    clojure/common-lisp/emacs-lisp too).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions