From 171a986f82a5d9773c0ba9a76f751b724e28312f Mon Sep 17 00:00:00 2001 From: Brummel Date: Thu, 28 May 2026 19:21:57 +0200 Subject: [PATCH] =?UTF-8?q?fix(stub):=20add=20missing=20(fn=20new=20...)?= =?UTF-8?q?=20to=20STUB=5FAIL=20=E2=80=94=20restore=20prep.3=20spec/ship?= =?UTF-8?q?=20coherence=20(refs=20F4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fieldtest F4 surfaced that the shipped STUB_AIL had only the TypeDef + ctor; the spec's prep.3 § "Worked author example" wired a `(fn new ...)` def into the stub and immediately exercised it via the worked consumer's `(new StubT 42)`. The implementer dropped the def during the Task 6 sweep (spec-review let it through). Without the def, the stub's `Term::New` end-to-end ratification story is broken — F4 demonstrated this with a `new-type-not-constructible` diagnostic on a verbatim worked-consumer paste. Re-added the def per the spec's design: (fn new (doc "Construct StubT from an Int. Exercises Term::New end-to-end.") (type (fn-type (params (con Int)) (ret (con StubT (con Int))))) (params x) (body (term-ctor StubT Stub x))) IR snapshots refreshed because every binary now carries the `new` function's IR (in addition to the `drop_kernel_stub_StubT` from the original prep.3 close). All 664 workspace tests green. This restores coherence between the spec, the design model, and the shipped stub. The `Term::New` invocation `(new StubT 42)` is still codegen-deferred (per spec § Architecture, raw-buf milestone); but at least `ail check` now passes on the spec's worked-consumer paste. A related and more substantive bug (F3 — kernel-tier auto-import not registering the module as a qualifier prefix, making `kernel_stub.StubT` consumer-unreachable) is handled separately via the debug skill. --- crates/ail/tests/snapshots/hello.ll | 16 ++++++++++++++++ crates/ail/tests/snapshots/list.ll | 16 ++++++++++++++++ crates/ail/tests/snapshots/max3.ll | 16 ++++++++++++++++ crates/ail/tests/snapshots/sum.ll | 16 ++++++++++++++++ crates/ail/tests/snapshots/ws_main.ll | 16 ++++++++++++++++ crates/ailang-kernel-stub/src/lib.rs | 12 +++++++++++- 6 files changed, 91 insertions(+), 1 deletion(-) diff --git a/crates/ail/tests/snapshots/hello.ll b/crates/ail/tests/snapshots/hello.ll index 35bfdbe..1bcd965 100644 --- a/crates/ail/tests/snapshots/hello.ll +++ b/crates/ail/tests/snapshots/hello.ll @@ -25,6 +25,7 @@ declare ptr @ailang_str_concat(ptr, ptr) declare i64 @llvm.fptosi.sat.i64.f64(double) @ail_hello_main_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_hello_main_adapter, ptr null } +@ail_kernel_stub_new_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_kernel_stub_new_adapter, ptr null } @ail_prelude_float_eq_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_eq_adapter, ptr null } @ail_prelude_float_ne_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_ne_adapter, ptr null } @ail_prelude_float_lt_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_lt_adapter, ptr null } @@ -45,6 +46,21 @@ entry: ret i8 %r } +define ptr @ail_kernel_stub_new(i64 %arg_x) { +entry: + %v1 = call ptr @ailang_rc_alloc(i64 16) + store i64 0, ptr %v1, align 8 + %v2 = getelementptr inbounds i8, ptr %v1, i64 8 + store i64 %arg_x, ptr %v2, align 8 + ret ptr %v1 +} + +define ptr @ail_kernel_stub_new_adapter(ptr %_env, i64 %a0) { +entry: + %r = call ptr @ail_kernel_stub_new(i64 %a0) + ret ptr %r +} + define void @drop_kernel_stub_StubT(ptr %p) { entry: %is_null = icmp eq ptr %p, null diff --git a/crates/ail/tests/snapshots/list.ll b/crates/ail/tests/snapshots/list.ll index 5d5a167..2cccf45 100644 --- a/crates/ail/tests/snapshots/list.ll +++ b/crates/ail/tests/snapshots/list.ll @@ -22,6 +22,7 @@ declare ptr @ailang_str_clone(ptr) declare ptr @ailang_str_concat(ptr, ptr) declare i64 @llvm.fptosi.sat.i64.f64(double) +@ail_kernel_stub_new_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_kernel_stub_new_adapter, ptr null } @ail_list_sum_list_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_list_sum_list_adapter, ptr null } @ail_list_main_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_list_main_adapter, ptr null } @ail_prelude_float_eq_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_eq_adapter, ptr null } @@ -32,6 +33,21 @@ declare i64 @llvm.fptosi.sat.i64.f64(double) @ail_prelude_float_ge_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_ge_adapter, ptr null } @ail_prelude_show__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_show__Int_adapter, ptr null } @ail_prelude_print__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_print__Int_adapter, ptr null } +define ptr @ail_kernel_stub_new(i64 %arg_x) { +entry: + %v1 = call ptr @ailang_rc_alloc(i64 16) + store i64 0, ptr %v1, align 8 + %v2 = getelementptr inbounds i8, ptr %v1, i64 8 + store i64 %arg_x, ptr %v2, align 8 + ret ptr %v1 +} + +define ptr @ail_kernel_stub_new_adapter(ptr %_env, i64 %a0) { +entry: + %r = call ptr @ail_kernel_stub_new(i64 %a0) + ret ptr %r +} + define void @drop_kernel_stub_StubT(ptr %p) { entry: %is_null = icmp eq ptr %p, null diff --git a/crates/ail/tests/snapshots/max3.ll b/crates/ail/tests/snapshots/max3.ll index 56b21d8..f1fffca 100644 --- a/crates/ail/tests/snapshots/max3.ll +++ b/crates/ail/tests/snapshots/max3.ll @@ -22,6 +22,7 @@ declare ptr @ailang_str_clone(ptr) declare ptr @ailang_str_concat(ptr, ptr) declare i64 @llvm.fptosi.sat.i64.f64(double) +@ail_kernel_stub_new_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_kernel_stub_new_adapter, ptr null } @ail_max3_max_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_max3_max_adapter, ptr null } @ail_max3_max3_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_max3_max3_adapter, ptr null } @ail_max3_main_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_max3_main_adapter, ptr null } @@ -35,6 +36,21 @@ declare i64 @llvm.fptosi.sat.i64.f64(double) @ail_prelude_gt__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_gt__Int_adapter, ptr null } @ail_prelude_show__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_show__Int_adapter, ptr null } @ail_prelude_print__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_print__Int_adapter, ptr null } +define ptr @ail_kernel_stub_new(i64 %arg_x) { +entry: + %v1 = call ptr @ailang_rc_alloc(i64 16) + store i64 0, ptr %v1, align 8 + %v2 = getelementptr inbounds i8, ptr %v1, i64 8 + store i64 %arg_x, ptr %v2, align 8 + ret ptr %v1 +} + +define ptr @ail_kernel_stub_new_adapter(ptr %_env, i64 %a0) { +entry: + %r = call ptr @ail_kernel_stub_new(i64 %a0) + ret ptr %r +} + define void @drop_kernel_stub_StubT(ptr %p) { entry: %is_null = icmp eq ptr %p, null diff --git a/crates/ail/tests/snapshots/sum.ll b/crates/ail/tests/snapshots/sum.ll index e6ccdd9..19a0eea 100644 --- a/crates/ail/tests/snapshots/sum.ll +++ b/crates/ail/tests/snapshots/sum.ll @@ -22,6 +22,7 @@ declare ptr @ailang_str_clone(ptr) declare ptr @ailang_str_concat(ptr, ptr) declare i64 @llvm.fptosi.sat.i64.f64(double) +@ail_kernel_stub_new_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_kernel_stub_new_adapter, ptr null } @ail_prelude_float_eq_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_eq_adapter, ptr null } @ail_prelude_float_ne_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_ne_adapter, ptr null } @ail_prelude_float_lt_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_lt_adapter, ptr null } @@ -33,6 +34,21 @@ declare i64 @llvm.fptosi.sat.i64.f64(double) @ail_prelude_print__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_print__Int_adapter, ptr null } @ail_sum_sum_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_sum_sum_adapter, ptr null } @ail_sum_main_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_sum_main_adapter, ptr null } +define ptr @ail_kernel_stub_new(i64 %arg_x) { +entry: + %v1 = call ptr @ailang_rc_alloc(i64 16) + store i64 0, ptr %v1, align 8 + %v2 = getelementptr inbounds i8, ptr %v1, i64 8 + store i64 %arg_x, ptr %v2, align 8 + ret ptr %v1 +} + +define ptr @ail_kernel_stub_new_adapter(ptr %_env, i64 %a0) { +entry: + %r = call ptr @ail_kernel_stub_new(i64 %a0) + ret ptr %r +} + define void @drop_kernel_stub_StubT(ptr %p) { entry: %is_null = icmp eq ptr %p, null diff --git a/crates/ail/tests/snapshots/ws_main.ll b/crates/ail/tests/snapshots/ws_main.ll index f3ec33f..931c9db 100644 --- a/crates/ail/tests/snapshots/ws_main.ll +++ b/crates/ail/tests/snapshots/ws_main.ll @@ -22,6 +22,7 @@ declare ptr @ailang_str_clone(ptr) declare ptr @ailang_str_concat(ptr, ptr) declare i64 @llvm.fptosi.sat.i64.f64(double) +@ail_kernel_stub_new_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_kernel_stub_new_adapter, ptr null } @ail_prelude_float_eq_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_eq_adapter, ptr null } @ail_prelude_float_ne_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_ne_adapter, ptr null } @ail_prelude_float_lt_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_float_lt_adapter, ptr null } @@ -32,6 +33,21 @@ declare i64 @llvm.fptosi.sat.i64.f64(double) @ail_prelude_print__Int_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_prelude_print__Int_adapter, ptr null } @ail_ws_lib_add_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_ws_lib_add_adapter, ptr null } @ail_ws_main_main_clos = private unnamed_addr constant { ptr, ptr } { ptr @ail_ws_main_main_adapter, ptr null } +define ptr @ail_kernel_stub_new(i64 %arg_x) { +entry: + %v1 = call ptr @ailang_rc_alloc(i64 16) + store i64 0, ptr %v1, align 8 + %v2 = getelementptr inbounds i8, ptr %v1, i64 8 + store i64 %arg_x, ptr %v2, align 8 + ret ptr %v1 +} + +define ptr @ail_kernel_stub_new_adapter(ptr %_env, i64 %a0) { +entry: + %r = call ptr @ail_kernel_stub_new(i64 %a0) + ret ptr %r +} + define void @drop_kernel_stub_StubT(ptr %p) { entry: %is_null = icmp eq ptr %p, null diff --git a/crates/ailang-kernel-stub/src/lib.rs b/crates/ailang-kernel-stub/src/lib.rs index 6509b9e..ff49bec 100644 --- a/crates/ailang-kernel-stub/src/lib.rs +++ b/crates/ailang-kernel-stub/src/lib.rs @@ -19,9 +19,19 @@ /// Source-of-truth Form-A text for the stub kernel module. Parsed /// by `ailang_surface::parse_kernel_stub` (and round-trip-pinned by /// `kernel_stub_module_round_trips` in `design_schema_drift.rs`). +/// +/// Ships a `(fn new ...)` def so consumers can spell `(new StubT 42)`, +/// the worked-consumer example from prep.3 of the spec — without it, +/// the stub's `Term::New` end-to-end ratification story is broken +/// (per fieldtest F4, 2026-05-28). pub const STUB_AIL: &str = r#"(module kernel_stub (kernel) (data StubT (vars a) (ctor Stub a) - (param-in (a Int Float)))) + (param-in (a Int Float))) + (fn new + (doc "Construct StubT from an Int. Exercises Term::New end-to-end.") + (type (fn-type (params (con Int)) (ret (con StubT (con Int))))) + (params x) + (body (term-ctor StubT Stub x)))) "#;