iter form-a.1 (Tasks 1-5): additive phase + relocation

First half of the form-a-default-authoring milestone-close iter
(Boss-decided strategy C, big-bang). All five tasks DONE; cargo
test --workspace green at every per-task boundary.

T1 — Add three new tests:
- parse_is_deterministic_over_every_ail_fixture (round_trip.rs)
- cli_parse_then_render_then_parse_is_idempotent (roundtrip_cli.rs)
- carve_out_inventory.rs (new file; #[ignore]'d until T8 deletion)

T2 — Bulk-render the 99 missing examples/<stem>.ail files via
`ail render`. Corpus 58 .ail (pre-iter) -> 157 .ail. Eight .ail.json
carve-outs (7 §C4(a) subject-matter + 1 §C4(b) prelude) preserved.
One re-loop triggered: load_workspace prefers .ail siblings since
ext-cli.1, so the newly-rendered imports broke seven Group-A entries
whose JSON entry-paths now resolved imports to fresh .ail. Repair:
pre-emptive forward-pull of five T3 migrations + 4 transient
#[ignore]s on workspace.rs mod tests (cleanly relocated in T5).

T3 — 14 Group-A test files migrated from ailang_core::load_workspace
to ailang_surface::load_workspace + .ail paths. Carve-out lines
preserved verbatim (7 sites in typeclass_22b2.rs / typeclass_22b3.rs).

T4 — 12 Group-B test files: bulk regex flip on build_and_run /
build_and_run_with_alloc / build_and_run_with_rc_stats call sites
(~70 e2e.rs invocations + 11 subprocess sites). Four files
mis-classified Group-A as Group-B in plan recon (mono_hash_stability,
prelude_free_fns, print_mono_body_shape, show_mono_synthesis); two
files mis-classified Group-B as Group-A (mono_recursive_fn,
mono_xmod_qualified_ref). Migrated per actual shape, not plan label.

T5 — Relocated #[cfg(test)] mod tests from production source to
integration test crates with ailang-surface dev-dependency:
- crates/ailang-core/tests/hash_pin.rs (10 tests from hash.rs)
- crates/ailang-core/tests/workspace_pin.rs (10 non-carve-out tests
  from workspace.rs)
- crates/ailang-codegen/tests/eq_primitives_pin.rs (3 tests from
  codegen/src/lib.rs:3717-3799)
- ailang-prose/tests/snapshot.rs migrated (helper + 8 fixtures) to
  .ail + ailang_surface::load_module
Carve-out tests in workspace.rs mod tests preserved in-place
(3× 22b2 + 3× ct1 = 6 tests). Tempdir-based loader-mechanism tests
(3 sites) also preserved — they don't consume examples/.

Tests: 560 passed, 0 failed, 4 ignored (was 558 + 3 T1 new -
1 transit carve_out_inventory #[ignore] = 560 active).

Tasks 6-12 (bench-driver suffix flips, e2e diff-test rewrite + 4
additional raw-JSON-inspect handlers, .ail.json deletion, retiring
obsolete roundtrip tests + schema_coverage corpus flip, §C3
DESIGN.md restatement, §A4 doctrine edits, WhatsNew + roadmap
strike) ship in the next dispatch on this iter ID.

Known debt inherited to T6-12: 4 raw-JSON-inspect tests in e2e.rs
(borrow_own_demo / reuse_as_demo / render_parse_round_trip_canonical
/ ail_run_accepts_ail_source_with_same_stdout_as_ail_json dual-form
smoke) need rewrite or #[ignore] before T8 deletion; recorded in
journal Concerns + Known debt sections.
This commit is contained in:
2026-05-13 11:12:48 +02:00
parent 1a065b37f1
commit 77b28ad64d
142 changed files with 2314 additions and 840 deletions
+69 -69
View File
@@ -78,7 +78,7 @@ fn build_and_run_with_alloc(example: &str, alloc: &str) -> String {
#[test]
fn sum_1_to_10_is_55() {
let stdout = build_and_run("sum.ail.json");
let stdout = build_and_run("sum.ail");
assert_eq!(stdout.trim(), "55");
}
@@ -86,20 +86,20 @@ fn sum_1_to_10_is_55() {
/// phi block tracking would produce a wrong result here.
#[test]
fn max3_picks_largest() {
let stdout = build_and_run("max3.ail.json");
let stdout = build_and_run("max3.ail");
assert_eq!(stdout.trim(), "17");
}
#[test]
fn hello_world_str_lit() {
let stdout = build_and_run("hello.ail.json");
let stdout = build_and_run("hello.ail");
assert_eq!(stdout.trim(), "Hello, AILang.");
}
/// Guards ADT codegen + match: recursive list, sum_list via match on Cons/Nil.
#[test]
fn list_sum_via_match() {
let stdout = build_and_run("list.ail.json");
let stdout = build_and_run("list.ail");
assert_eq!(stdout.trim(), "42");
}
@@ -107,7 +107,7 @@ fn list_sum_via_match() {
/// produce 42, exercising fn-typed parameters and indirect call.
#[test]
fn higher_order_apply_inc() {
let stdout = build_and_run("hof.ail.json");
let stdout = build_and_run("hof.ail");
assert_eq!(stdout.trim(), "42");
}
@@ -117,7 +117,7 @@ fn higher_order_apply_inc() {
/// and apply's indirect call unpacks both halves.
#[test]
fn closure_captures_let_n() {
let stdout = build_and_run("closure.ail.json");
let stdout = build_and_run("closure.ail");
assert_eq!(stdout.trim(), "42");
}
@@ -127,7 +127,7 @@ fn closure_captures_let_n() {
/// `map (\x. x * 2)` over `[1, 2, 3]` then print each element.
#[test]
fn list_map_doubles_then_prints() {
let stdout = build_and_run("list_map.ail.json");
let stdout = build_and_run("list_map.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["2", "4", "6"]);
}
@@ -141,7 +141,7 @@ fn list_map_doubles_then_prints() {
/// effectful tail call.
#[test]
fn list_map_poly_inc_then_prints() {
let stdout = build_and_run("list_map_poly.ail.json");
let stdout = build_and_run("list_map_poly.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["2", "3", "4"]);
}
@@ -156,7 +156,7 @@ fn list_map_poly_inc_then_prints() {
/// scrutinee with a wildcard fallback is not currently in the grammar.
#[test]
fn gc_handles_recursive_list_construction() {
let stdout = build_and_run("gc_stress.ail.json");
let stdout = build_and_run("gc_stress.ail");
assert_eq!(
stdout.trim(),
"1275",
@@ -177,7 +177,7 @@ fn gc_handles_recursive_list_construction() {
/// for the Box and zero `@GC_malloc` calls inside `peek`/`count`.
#[test]
fn iter17a_local_box_alloca() {
let stdout = build_and_run("escape_local_demo.ail.json");
let stdout = build_and_run("escape_local_demo.ail");
assert_eq!(
stdout.lines().collect::<Vec<_>>(),
vec!["42", "42", "5", "0"],
@@ -190,7 +190,7 @@ fn iter17a_local_box_alloca() {
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let src = workspace
.join("examples")
.join("escape_local_demo.ail.json");
.join("escape_local_demo.ail");
let tmp = std::env::temp_dir().join(format!(
"ailang_iter17a_alloca_{}",
std::process::id()
@@ -237,7 +237,7 @@ fn iter17a_local_box_alloca() {
fn iter14e_print_list_recursion_emits_musttail() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let src = workspace.join("examples").join("list_map_poly.ail.json");
let src = workspace.join("examples").join("list_map_poly.ail");
let tmp = std::env::temp_dir().join(format!(
"ailang_iter14e_musttail_{}",
std::process::id()
@@ -290,7 +290,7 @@ fn iter14e_print_list_recursion_emits_musttail() {
/// recursion + branching without surprises.
#[test]
fn insertion_sort_orders_list() {
let stdout = build_and_run("sort.ail.json");
let stdout = build_and_run("sort.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(
lines,
@@ -303,7 +303,7 @@ fn insertion_sort_orders_list() {
/// triggers a separate specialised LLVM fn. Output: 42, then "true".
#[test]
fn polymorphic_id_at_int_and_bool() {
let stdout = build_and_run("poly_id.ail.json");
let stdout = build_and_run("poly_id.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["42", "true"]);
}
@@ -314,7 +314,7 @@ fn polymorphic_id_at_int_and_bool() {
/// monomorphised body (a fn-typed param survives substitution).
#[test]
fn polymorphic_apply_with_fn_param() {
let stdout = build_and_run("poly_apply.ail.json");
let stdout = build_and_run("poly_apply.ail");
assert_eq!(stdout.trim(), "42");
}
@@ -326,7 +326,7 @@ fn polymorphic_apply_with_fn_param() {
/// down into a polymorphic fn body.
#[test]
fn parameterised_box_round_trip() {
let stdout = build_and_run("box.ail.json");
let stdout = build_and_run("box.ail");
assert_eq!(stdout.trim(), "42");
}
@@ -336,7 +336,7 @@ fn parameterised_box_round_trip() {
/// `x : Int`, not `x : a`).
#[test]
fn parameterised_maybe_match() {
let stdout = build_and_run("maybe_int.ail.json");
let stdout = build_and_run("maybe_int.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["7", "99"]);
}
@@ -351,7 +351,7 @@ fn parameterised_maybe_match() {
/// flows end-to-end through check, codegen, and runtime.
#[test]
fn cross_module_maybe_demo() {
let stdout = build_and_run("std_maybe_demo.ail.json");
let stdout = build_and_run("std_maybe_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["7", "99", "true", "true", "42"]);
}
@@ -365,7 +365,7 @@ fn cross_module_maybe_demo() {
/// and fail to unify against the qualified scrutinee args.
#[test]
fn std_list_demo() {
let stdout = build_and_run("std_list_demo.ail.json");
let stdout = build_and_run("std_list_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(
lines,
@@ -395,7 +395,7 @@ fn std_list_demo() {
/// happens at N=1000.
#[test]
fn std_list_stress_1000_element_folds() {
let stdout = build_and_run("std_list_stress.ail.json");
let stdout = build_and_run("std_list_stress.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(
lines,
@@ -457,7 +457,7 @@ fn render_parse_round_trip_canonical() {
/// the inner binders would be silently dropped by the codegen.
#[test]
fn nested_ctor_pattern_first_two_sum() {
let stdout = build_and_run("nested_pat.ail.json");
let stdout = build_and_run("nested_pat.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["30"]);
}
@@ -471,7 +471,7 @@ fn nested_ctor_pattern_first_two_sum() {
/// for the substituted MkPair output.
#[test]
fn std_pair_demo() {
let stdout = build_and_run("std_pair_demo.ail.json");
let stdout = build_and_run("std_pair_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["7", "9", "9", "7", "8", "18"]);
}
@@ -488,7 +488,7 @@ fn std_pair_demo() {
/// another instantiation.
#[test]
fn std_either_demo() {
let stdout = build_and_run("std_either_demo.ail.json");
let stdout = build_and_run("std_either_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(
lines,
@@ -513,7 +513,7 @@ fn std_either_demo() {
/// `[Left 1, Right 10, Left 2, Right 20, Right 30]`.
#[test]
fn std_either_list_demo() {
let stdout = build_and_run("std_either_list_demo.ail.json");
let stdout = build_and_run("std_either_list_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["2", "3", "2", "3"]);
}
@@ -528,7 +528,7 @@ fn std_either_list_demo() {
/// n>length) on each combinator. Expected stdout: 0, 3, 5, 5, 3, 0.
#[test]
fn std_list_more_demo() {
let stdout = build_and_run("std_list_more_demo.ail.json");
let stdout = build_and_run("std_list_more_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["0", "3", "5", "5", "3", "0"]);
}
@@ -546,7 +546,7 @@ fn std_list_more_demo() {
/// wrong values.
#[test]
fn local_rec_factorial_demo() {
let stdout = build_and_run("local_rec_demo.ail.json");
let stdout = build_and_run("local_rec_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["1", "6", "120"]);
}
@@ -563,7 +563,7 @@ fn local_rec_factorial_demo() {
/// sum_below(10)=45.
#[test]
fn local_rec_capture_demo() {
let stdout = build_and_run("local_rec_capture.ail.json");
let stdout = build_and_run("local_rec_capture.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["0", "10", "45"]);
}
@@ -581,7 +581,7 @@ fn local_rec_capture_demo() {
/// count_below(15)=9 (i in 1..9 are below threshold 10).
#[test]
fn local_rec_let_capture_demo() {
let stdout = build_and_run("local_rec_let_capture.ail.json");
let stdout = build_and_run("local_rec_let_capture.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["0", "5", "9"]);
}
@@ -601,7 +601,7 @@ fn local_rec_let_capture_demo() {
/// count_below(MkPair 10 15)=9.
#[test]
fn local_rec_match_capture_demo() {
let stdout = build_and_run("local_rec_match_capture.ail.json");
let stdout = build_and_run("local_rec_match_capture.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["0", "5", "9"]);
}
@@ -617,7 +617,7 @@ fn local_rec_match_capture_demo() {
/// Expected stdout: 120 (= apply5 factorial = factorial 5).
#[test]
fn local_rec_as_value_demo() {
let stdout = build_and_run("local_rec_as_value.ail.json");
let stdout = build_and_run("local_rec_as_value.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["120"]);
}
@@ -633,7 +633,7 @@ fn local_rec_as_value_demo() {
/// Expected stdout: 1320 (= 5*4*3*2*(1+10)), 12120 (= 5*4*3*2*(1+100)).
#[test]
fn local_rec_as_value_capture_demo() {
let stdout = build_and_run("local_rec_as_value_capture.ail.json");
let stdout = build_and_run("local_rec_as_value_capture.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["1320", "12120"]);
}
@@ -661,7 +661,7 @@ fn local_rec_as_value_capture_demo() {
/// applied 4 times to false — even count of flips ⇒ false).
#[test]
fn poly_rec_capture_demo() {
let stdout = build_and_run("poly_rec_capture.ail.json");
let stdout = build_and_run("poly_rec_capture.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["5", "false"]);
}
@@ -686,7 +686,7 @@ fn poly_rec_capture_demo() {
/// 1..=n. Expected stdout: 1, 6, 15 for n in {1, 3, 5}.
#[test]
fn nested_let_rec_demo() {
let stdout = build_and_run("nested_let_rec.ail.json");
let stdout = build_and_run("nested_let_rec.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["1", "6", "15"]);
}
@@ -781,7 +781,7 @@ fn diff_detects_changed_def() {
fn diff_no_changes_exit_zero() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let src = workspace.join("examples").join("sum.ail.json");
let src = workspace.join("examples").join("sum.ail");
let output = Command::new(ail_bin())
.args([
@@ -822,7 +822,7 @@ fn diff_no_changes_exit_zero() {
fn workspace_lists_imported_modules() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let entry = workspace.join("examples").join("ws_main.ail.json");
let entry = workspace.join("examples").join("ws_main.ail");
let output = Command::new(ail_bin())
.args(["workspace", entry.to_str().unwrap(), "--json"])
@@ -866,7 +866,7 @@ fn workspace_lists_imported_modules() {
fn check_workspace_resolves_import() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let entry = workspace.join("examples").join("ws_main.ail.json");
let entry = workspace.join("examples").join("ws_main.ail");
let output = Command::new(ail_bin())
.args(["check", entry.to_str().unwrap(), "--json"])
@@ -891,7 +891,7 @@ fn check_workspace_resolves_import() {
/// `@ail_ws_main_main` must call `@ail_ws_lib_add(2,3)` and print `5`.
#[test]
fn workspace_build_runs_imported_fn() {
let stdout = build_and_run("ws_main.ail.json");
let stdout = build_and_run("ws_main.ail");
assert_eq!(stdout.trim(), "5", "ws_lib.add(2,3) should print 5");
}
@@ -904,7 +904,7 @@ fn workspace_build_runs_imported_fn() {
/// `imports: ["prelude"]` entry in the source module.
#[test]
fn ordering_match_via_prelude_prints_1() {
let stdout = build_and_run("ordering_match.ail.json");
let stdout = build_and_run("ordering_match.ail");
assert_eq!(stdout, "1\n");
}
@@ -923,7 +923,7 @@ fn ordering_match_via_prelude_prints_1() {
/// is type-driven, and the run completes cleanly.
#[test]
fn compare_primitives_smoke_prints_1_2_3_thrice() {
let stdout = build_and_run("compare_primitives_smoke.ail.json");
let stdout = build_and_run("compare_primitives_smoke.ail");
assert_eq!(stdout, "1\n2\n3\n1\n2\n3\n1\n2\n3\n");
}
@@ -935,7 +935,7 @@ fn compare_primitives_smoke_prints_1_2_3_thrice() {
/// call. Equal-call lines are `1`, unequal-call lines are `0`.
#[test]
fn eq_primitives_smoke_compiles_and_runs() {
let stdout = build_and_run("eq_primitives_smoke.ail.json");
let stdout = build_and_run("eq_primitives_smoke.ail");
assert_eq!(stdout, "1\n0\n1\n0\n1\n0\n");
}
@@ -945,7 +945,7 @@ fn eq_primitives_smoke_compiles_and_runs() {
fn manifest_workspace_lists_all_defs() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let entry = workspace.join("examples").join("ws_main.ail.json");
let entry = workspace.join("examples").join("ws_main.ail");
let output = Command::new(ail_bin())
.args([
@@ -988,7 +988,7 @@ fn manifest_workspace_lists_all_defs() {
fn describe_workspace_resolves_qualified_name() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let entry = workspace.join("examples").join("ws_main.ail.json");
let entry = workspace.join("examples").join("ws_main.ail");
let output = Command::new(ail_bin())
.args([
@@ -1031,7 +1031,7 @@ fn describe_workspace_resolves_qualified_name() {
fn deps_filters_builtins_params_locals() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let src = workspace.join("examples").join("sum.ail.json");
let src = workspace.join("examples").join("sum.ail");
let output = Command::new(ail_bin())
.args(["deps", src.to_str().unwrap(), "--of", "sum", "--json"])
@@ -1070,7 +1070,7 @@ fn deps_filters_builtins_params_locals() {
fn deps_workspace_filters_builtins_and_params() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let entry = workspace.join("examples").join("ws_main.ail.json");
let entry = workspace.join("examples").join("ws_main.ail");
let output = Command::new(ail_bin())
.args(["deps", entry.to_str().unwrap(), "--workspace", "--json"])
@@ -1096,7 +1096,7 @@ fn deps_workspace_filters_builtins_and_params() {
fn deps_workspace_includes_cross_module() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let workspace = Path::new(manifest_dir).parent().unwrap().parent().unwrap();
let entry = workspace.join("examples").join("ws_main.ail.json");
let entry = workspace.join("examples").join("ws_main.ail");
let output = Command::new(ail_bin())
.args(["deps", entry.to_str().unwrap(), "--workspace", "--json"])
@@ -1266,7 +1266,7 @@ fn check_json_unbound_var() {
/// chain default).
#[test]
fn lit_pat_demo() {
let stdout = build_and_run("lit_pat.ail.json");
let stdout = build_and_run("lit_pat.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["100", "200", "999", "-1", "0", "7"]);
}
@@ -1281,7 +1281,7 @@ fn lit_pat_demo() {
/// print the expected outputs.
#[test]
fn unreachable_demo() {
let stdout = build_and_run("unreachable_demo.ail.json");
let stdout = build_and_run("unreachable_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["4", "5"]);
}
@@ -1321,7 +1321,7 @@ fn borrow_own_demo_modes_are_metadata_only() {
"expected `param_modes:[\"own\"]` in canonical JSON; the schema for `(own T)` regressed"
);
let stdout = build_and_run("borrow_own_demo.ail.json");
let stdout = build_and_run("borrow_own_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["3", "6"]);
}
@@ -1338,7 +1338,7 @@ fn borrow_own_demo_modes_are_metadata_only() {
/// non-Int args at typecheck.
#[test]
fn eq_demo() {
let stdout = build_and_run("eq_demo.ail.json");
let stdout = build_and_run("eq_demo.ail");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(
lines,
@@ -1374,7 +1374,7 @@ fn alloc_rc_produces_same_stdout_as_gc() {
/// passthrough with `call void @ailang_rc_inc` under `--alloc=rc`.
#[test]
fn clone_demo_is_identity_in_18c1() {
let stdout = build_and_run("clone_demo.ail.json");
let stdout = build_and_run("clone_demo.ail");
assert_eq!(stdout.trim(), "42");
}
@@ -1413,11 +1413,11 @@ fn reuse_as_demo_under_rc_uses_inplace_rewrite() {
);
// (2) gc baseline.
let stdout_gc = build_and_run_with_alloc("reuse_as_demo.ail.json", "gc");
let stdout_gc = build_and_run_with_alloc("reuse_as_demo.ail", "gc");
assert_eq!(stdout_gc.trim(), "9");
// (3) rc matches gc, (4) clean exit (build_and_run_with_alloc
// panics on non-zero status).
let stdout_rc = build_and_run_with_alloc("reuse_as_demo.ail.json", "rc");
let stdout_rc = build_and_run_with_alloc("reuse_as_demo.ail", "rc");
assert_eq!(stdout_rc.trim(), "9");
// (5) Inspect the rc IR text. We re-lower via the codegen API
@@ -2176,7 +2176,7 @@ fn build_and_run_with_rc_stats(example: &str) -> (String, u64, u64, i64) {
#[test]
fn alloc_rc_explicit_mode_tail_sum_does_not_leak_outer_cells() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("rc_tail_sum_explicit_leak.ail.json");
build_and_run_with_rc_stats("rc_tail_sum_explicit_leak.ail");
assert_eq!(
stdout.trim(),
"4950",
@@ -2211,7 +2211,7 @@ fn alloc_rc_explicit_mode_tail_sum_does_not_leak_outer_cells() {
#[test]
fn alloc_rc_let_binder_for_owned_returning_app_drops_at_scope_close() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("rc_let_owned_app_leak.ail.json");
build_and_run_with_rc_stats("rc_let_owned_app_leak.ail");
assert_eq!(
stdout.trim(),
"1",
@@ -2255,7 +2255,7 @@ fn alloc_rc_let_binder_for_owned_returning_app_drops_at_scope_close() {
#[test]
fn alloc_rc_let_binder_for_implicit_returning_app_does_not_drop() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("rc_let_implicit_returning_app.ail.json");
build_and_run_with_rc_stats("rc_let_implicit_returning_app.ail");
assert_eq!(stdout.trim(), "7", "alloc(7) -> unbox should print 7");
assert_eq!(
live, 1,
@@ -2339,7 +2339,7 @@ fn alloc_rc_let_alias_of_implicit_param_does_not_dec_borrowed_children() {
#[test]
fn alloc_rc_partial_drop_at_fn_return_does_not_leak_unmoved_fields() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("rc_own_param_partial_drop_leak.ail.json");
build_and_run_with_rc_stats("rc_own_param_partial_drop_leak.ail");
assert_eq!(
stdout.trim(),
"1",
@@ -2378,7 +2378,7 @@ fn alloc_rc_partial_drop_at_fn_return_does_not_leak_unmoved_fields() {
#[test]
fn alloc_rc_partial_drop_at_arm_close_does_not_leak_unmoved_fields() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("rc_match_arm_partial_drop_leak.ail.json");
build_and_run_with_rc_stats("rc_match_arm_partial_drop_leak.ail");
assert_eq!(
stdout.trim(),
"1",
@@ -2411,7 +2411,7 @@ fn alloc_rc_partial_drop_at_arm_close_does_not_leak_unmoved_fields() {
#[test]
fn alloc_rc_partial_drop_at_app_let_close_does_not_leak_unmoved_fields() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("rc_app_let_partial_drop_leak.ail.json");
build_and_run_with_rc_stats("rc_app_let_partial_drop_leak.ail");
assert_eq!(
stdout.trim(),
"1",
@@ -2571,7 +2571,7 @@ fn ail_run_accepts_ail_source_with_same_stdout_as_ail_json() {
/// every alloc strategy after the hs.4 hoist).
#[test]
fn int_to_str_smoke() {
let out = build_and_run("int_to_str_smoke.ail.json");
let out = build_and_run("int_to_str_smoke.ail");
assert_eq!(out, "42\n");
}
@@ -2584,7 +2584,7 @@ fn int_to_str_smoke() {
/// trip-wire that surfaces it.
#[test]
fn float_to_str_smoke() {
let out = build_and_run("float_to_str_smoke.ail.json");
let out = build_and_run("float_to_str_smoke.ail");
assert_eq!(out, "3.5\n");
}
@@ -2600,7 +2600,7 @@ fn float_to_str_smoke() {
#[test]
fn int_to_str_drop_balances_rc_stats() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("int_to_str_drop_rc.ail.json");
build_and_run_with_rc_stats("int_to_str_drop_rc.ail");
assert_eq!(stdout, "42\n");
assert!(allocs >= 1, "expected at least one heap-Str allocation; got allocs={allocs}");
assert_eq!(allocs, frees, "every heap-Str alloc must be freed; allocs={allocs}, frees={frees}");
@@ -2616,7 +2616,7 @@ fn int_to_str_drop_balances_rc_stats() {
#[test]
fn str_field_in_adt_drops_heap_str_correctly() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("str_field_in_adt_heap.ail.json");
build_and_run_with_rc_stats("str_field_in_adt_heap.ail");
assert_eq!(stdout, "42\n");
assert!(allocs >= 2, "expected ADT cell + heap-Str slab; got allocs={allocs}");
assert_eq!(allocs, frees, "every RC slab must be freed; allocs={allocs}, frees={frees}");
@@ -2631,7 +2631,7 @@ fn str_field_in_adt_drops_heap_str_correctly() {
#[test]
fn int_arg_to_effect_op_does_not_rc_track() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("int_to_print_int_borrow.ail.json");
build_and_run_with_rc_stats("int_to_print_int_borrow.ail");
assert_eq!(stdout, "7\n");
assert_eq!(allocs, 0, "Int arg should not trigger any RC alloc; got allocs={allocs}");
assert_eq!(frees, 0, "Int arg should not trigger any RC free; got frees={frees}");
@@ -2649,7 +2649,7 @@ fn int_arg_to_effect_op_does_not_rc_track() {
#[test]
fn heap_str_repeated_print_balances_rc_stats() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("heap_str_repeated_print_borrow.ail.json");
build_and_run_with_rc_stats("heap_str_repeated_print_borrow.ail");
assert_eq!(stdout, "42\n42\n");
assert_eq!(allocs, 1, "expected exactly one heap-Str slab; got allocs={allocs}");
assert_eq!(frees, 1, "expected exactly one free; got frees={frees}");
@@ -2665,7 +2665,7 @@ fn heap_str_repeated_print_balances_rc_stats() {
#[test]
fn bool_to_str_drop_balances_rc_stats() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("bool_to_str_drop_rc.ail.json");
build_and_run_with_rc_stats("bool_to_str_drop_rc.ail");
assert_eq!(stdout, "true\n");
assert_eq!(allocs, 1, "expected exactly one heap-Str slab; got allocs={allocs}");
assert_eq!(frees, 1, "expected exactly one free; got frees={frees}");
@@ -2678,7 +2678,7 @@ fn bool_to_str_drop_balances_rc_stats() {
/// "true" slab.
#[test]
fn bool_to_str_emits_true_branch() {
let out = build_and_run("bool_to_str_drop_rc.ail.json");
let out = build_and_run("bool_to_str_drop_rc.ail");
assert_eq!(out, "true\n");
}
@@ -2686,7 +2686,7 @@ fn bool_to_str_emits_true_branch() {
/// content of `ailang_bool_to_str`'s "false" slab.
#[test]
fn bool_to_str_emits_false_branch() {
let out = build_and_run("bool_to_str_smoke_false.ail.json");
let out = build_and_run("bool_to_str_smoke_false.ail");
assert_eq!(out, "false\n");
}
@@ -2698,7 +2698,7 @@ fn bool_to_str_emits_false_branch() {
#[test]
fn str_clone_drop_balances_rc_stats() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("str_clone_drop_rc.ail.json");
build_and_run_with_rc_stats("str_clone_drop_rc.ail");
assert_eq!(stdout, "hello\n");
assert_eq!(allocs, 1, "expected exactly one heap-Str clone slab; got allocs={allocs}");
assert_eq!(frees, 1, "expected exactly one free; got frees={frees}");
@@ -2716,7 +2716,7 @@ fn str_clone_drop_balances_rc_stats() {
#[test]
fn str_clone_cross_realisation_uniform_abi() {
let (stdout, allocs, frees, live) =
build_and_run_with_rc_stats("str_clone_cross_realisation.ail.json");
build_and_run_with_rc_stats("str_clone_cross_realisation.ail");
assert_eq!(stdout, "42\nabc\n");
assert_eq!(allocs, 3, "expected one int_to_str slab + two str_clone slabs; got allocs={allocs}");
assert_eq!(frees, 3, "expected three matching frees; got frees={frees}");