The corpus program for a cast that opens a box

This commit is contained in:
Joseph Ferano 2026-09-20 13:54:07 +07:00
parent b6ea14f930
commit 10610fb76b
3 changed files with 75 additions and 3 deletions

View File

@ -1219,8 +1219,8 @@ int32_t flan_dyn_cast_kind(flan_dyn v, const uint8_t *loc, int64_t loc_len,
"flan %.*s: (%.*s x) found a dyn holding %s, and converted it to "
"%.*s — warned once for this site\n",
(int)loc_len, (const char *)loc, (int)target_len,
(const char *)target, tag_of(v), (int)target_len,
(const char *)target);
(const char *)target, is_float ? "a float" : "an int",
(int)target_len, (const char *)target);
}
return is_float;
}

View File

@ -334,7 +334,7 @@ int32_t flan_dyn_cast_kind(flan_dyn v, const uint8_t *loc, int64_t loc_len,
"flan %.*s: (%.*s x) found a dyn holding %s, and converted it "
"to %.*s — warned once for this site\n",
(int)loc_len, (const char *)loc, (int)target_len,
(const char *)target, is_float ? "float" : "int",
(const char *)target, is_float ? "a float" : "an int",
(int)target_len, (const char *)target);
}
}

View File

@ -0,0 +1,72 @@
;;;; A numeric cast opens a dyn box — FIX.org 2026-09-20.
;;;;
;;;; Before this, a typed parameter was the only thing in the language that
;;;; could open a box, so a program wanting a number out of a dyn wrote a
;;;; one-line function whose parameter slot did the unboxing and called that.
;;;; A cast is the operator for "convert this to that", so it is the spelling
;;;; that should have worked; here it does.
;;;;
;;;; Three behaviours, in the order main runs them:
;;;;
;;;; 1. Same kind. The box holds what the cast asks for, so the cast is the
;;;; unbox and nothing else is written or warned.
;;;; 2. Cross kind. The box holds the other number. The cast still converts —
;;;; exactly as the same cast converts a typed operand of that type — and
;;;; one line goes to stderr naming the site. The two cross-kind casts here
;;;; sit inside a dotimes that runs them eight times each, and stderr gets
;;;; two lines, because the warning is per *site*: these casts live in frame
;;;; loops and a per-value line would be a flood rather than a diagnostic.
;;;; 3. A box holding something that is not a number. That still traps, the way
;;;; a typed parameter traps on it today, and the runtime owns the sentence.
;;;; It is the last thing main does, so everything above it has printed.
;; The box. Unannotated parameters are dyn, so this is the boxing site and the
;; call below is where a typed literal crosses in.
(defn as-dyn [x] dyn x)
(defn main [] ()
(let [i (as-dyn 7)
f (as-dyn 2.5)]
;; ── 1. Same kind: the cast is the unbox ──────────────────────────
;; An int box to every integer width, and a float box to both floats.
;; None of these warns: the box holds what was asked for.
(print (i64 i))
(print "\n")
(print (i64 (i32 i)))
(print "\n")
(print (i64 (u32 i)))
(print "\n")
(print (i64 (u8 i)))
(print "\n")
(print (f64 f))
(print "\n")
(print (f64 (f32 f)))
(print "\n")
;; ── 2. Cross kind: it converts, and warns once for the site ──────
;; (f64 int-box) is 7 -> 7.0, the same widening (f64 7) does on a typed
;; operand. (i64 float-box) is 2.5 -> 2, the same truncation toward zero
;; (i64 2.5) does — range-checked by the emitter's own check_cast, because
;; the arm really is that cast with an unbox in front of it.
;;
;; Eight turns of the loop, two sites, two lines on stderr.
(dotimes [n 8]
(print (f64 i))
(print "\n")
(print (i64 f))
(print "\n"))
;; A third site, and the third warning. An int box straight to f32 is one
;; sitofp from i64, which is what (f32 x) on a typed i64 is. Written down
;; because the tempting "fix" — go through f64 and then narrow — rounds
;; twice and is a different number for values an i64 can hold and an f64
;; cannot round to an f32 the same way.
(print (f64 (f32 i)))
(print "\n"))
;; ── 3. And the box that holds no number ──────────────────────────────
;; A bool, which is what the typed parameter boundary already refuses: a dyn
;; holding true does not satisfy an i64 there and does not satisfy (i64 x)
;; here. The runtime owns the message.
(print (i64 (as-dyn true)))
(print "\n"))