iter 22b.3.5: workspace fixpoint loop — dedup + synth-append
This commit is contained in:
@@ -49,25 +49,21 @@ fn monomorphise_workspace_is_identity_on_class_free_workspace() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Property: the Task 1 skeleton's class-present branch is also a
|
||||
/// no-op. The fixture has a `Def::Class` and a `Def::Instance` (so
|
||||
/// the early-out does NOT fire) but no concrete class-method call
|
||||
/// sites yet wired through the pipeline; under the skeleton, the
|
||||
/// fall-through `Ok(ws.clone())` must preserve every module's
|
||||
/// canonical hash.
|
||||
/// Property: when a workspace has a class + instance but no concrete
|
||||
/// class-method call sites, the mono pass produces a hash-identical
|
||||
/// workspace — the early-out path is bypassed (typeclasses present)
|
||||
/// but the fixpoint loop terminates on round 1 with zero new targets,
|
||||
/// so no FnDefs are appended.
|
||||
///
|
||||
/// NOTE: this test will need updating in Task 5 once the skeleton
|
||||
/// is replaced with the real fixpoint — at that point synth fns
|
||||
/// will be appended to the `defining_module`, breaking module-hash
|
||||
/// equality on that module by design. The test as written
|
||||
/// guarantees the Task 1 contract and catches accidental partial
|
||||
/// rewrites landed before Task 5.
|
||||
/// The fixture (`test_22b3_no_call_sites.ail.json`) declares
|
||||
/// `class Show` + `instance Show Int` with a Lam-shaped instance
|
||||
/// body, but `main` is a literal — there is no `show <x>` call at any
|
||||
/// type. Updated in Task 5 from `test_22b2_instance_present.ail.json`,
|
||||
/// which had a `show 42` call site that the real fixpoint now
|
||||
/// (correctly) materialises into `show#Int`.
|
||||
#[test]
|
||||
fn monomorphise_workspace_is_identity_when_no_concrete_call_sites() {
|
||||
// `test_22b2_instance_present.ail.json` has `class Show` +
|
||||
// `instance Show Int` and typechecks cleanly; reused across
|
||||
// 22b.2 tests so its shape is stable.
|
||||
let entry = examples_dir().join("test_22b2_instance_present.ail.json");
|
||||
let entry = examples_dir().join("test_22b3_no_call_sites.ail.json");
|
||||
let ws = ailang_core::load_workspace(&entry).expect("load");
|
||||
let diags = ailang_check::check_workspace(&ws);
|
||||
assert!(diags.is_empty(), "fixture must typecheck: {:?}", diags);
|
||||
@@ -82,14 +78,15 @@ fn monomorphise_workspace_is_identity_when_no_concrete_call_sites() {
|
||||
before.modules.keys().collect::<Vec<_>>(),
|
||||
"module set must be identical"
|
||||
);
|
||||
// Each module hashes byte-identical (skeleton clones unchanged).
|
||||
// Each module hashes byte-identical — no synth fns appended
|
||||
// because no call site triggered a target.
|
||||
for (mname, m) in &ws_after.modules {
|
||||
let before_m = &before.modules[mname];
|
||||
let h_after = ailang_core::module_hash(m);
|
||||
let h_before = ailang_core::module_hash(before_m);
|
||||
assert_eq!(
|
||||
h_after, h_before,
|
||||
"class-present module `{}` must hash-identical through Task 1 skeleton",
|
||||
"class-present-but-no-call-site module `{}` must hash-identical",
|
||||
mname
|
||||
);
|
||||
}
|
||||
@@ -366,3 +363,30 @@ fn synthesise_mono_fn_zero_arg_method_uses_body_verbatim() {
|
||||
f.body
|
||||
);
|
||||
}
|
||||
|
||||
/// Property: when two call sites of `show` apply at the same concrete
|
||||
/// type (Int), the workspace fixpoint synthesises the matching FnDef
|
||||
/// (`show#Int`) exactly once across the whole workspace. Verifies the
|
||||
/// dedup contract — the pass must not emit one FnDef per call site.
|
||||
#[test]
|
||||
fn fixpoint_dedupes_repeated_calls_at_same_type() {
|
||||
let entry = examples_dir().join("test_22b3_dup_call_sites.ail.json");
|
||||
let ws = ailang_core::load_workspace(&entry).expect("load");
|
||||
let diags = ailang_check::check_workspace(&ws);
|
||||
assert!(diags.is_empty(), "fixture must typecheck: {:?}", diags);
|
||||
|
||||
let ws = ailang_check::monomorphise_workspace(&ws).expect("mono");
|
||||
|
||||
// Count `show#Int` fns workspace-wide.
|
||||
let mut count = 0usize;
|
||||
for m in ws.modules.values() {
|
||||
for d in &m.defs {
|
||||
if let ailang_core::ast::Def::Fn(f) = d {
|
||||
if f.name == "show#Int" {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(count, 1, "exactly one show#Int across the workspace");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user