iter 22b.2.9: fix — superclass-walk tests, simplify class_superclasses map shape

This commit is contained in:
2026-05-09 18:59:15 +02:00
parent 7cff741632
commit b741a8ba05
4 changed files with 165 additions and 16 deletions
+43
View File
@@ -169,3 +169,46 @@ fn fn_with_correct_constraint_typechecks_green() {
diagnostics
);
}
/// Property protected: superclass-walk in `expand_declared_constraints`
/// covers the residual class produced by calling a superclass's method
/// from within a function constrained on the subclass. Concretely: the
/// fn declares `Ord a =>` and calls `eq` (an `Eq` method); the residual
/// `(Eq, a)` is satisfied because `Ord` extends `Eq`, so the expanded
/// declared set must include `(Eq, a)`. Without the superclass walk the
/// fn would spuriously fire `missing-constraint`. This is the positive
/// fixture for Decision 11's one-step superclass closure.
#[test]
fn fn_calling_superclass_method_via_subclass_constraint_typechecks_green() {
let entry = examples_dir()
.join("test_22b2_constraint_declared_via_superclass.ail.json");
let ws = ailang_core::workspace::load_workspace(&entry)
.expect("workspace loads");
let diagnostics = ailang_check::check_workspace(&ws);
assert!(
diagnostics.is_empty(),
"expected no diagnostics; superclass walk should have covered Eq via Ord; got: {:?}",
diagnostics
);
}
/// Property protected: the superclass walk goes from subclass to
/// superclass only — never the other direction. A fn that declares
/// `Eq a =>` and calls `lt` (an `Ord` method) must still fire
/// `missing-constraint` because `Ord` is a *sub*class of `Eq`, not a
/// superclass; the declared `(Eq, a)` does not cover the residual
/// `(Ord, a)`. Without this asymmetry, declaring the superclass would
/// spuriously satisfy any subclass residual.
#[test]
fn fn_with_superclass_constraint_calling_subclass_method_fires_missing_constraint() {
let entry = examples_dir()
.join("test_22b2_missing_constraint_subclass.ail.json");
let ws = ailang_core::workspace::load_workspace(&entry)
.expect("workspace loads");
let diagnostics = ailang_check::check_workspace(&ws);
assert!(
diagnostics.iter().any(|d| d.code == "missing-constraint"),
"expected missing-constraint; superclass walk should NOT cover sub-direction; got: {:?}",
diagnostics.iter().map(|d| &d.code).collect::<Vec<_>>()
);
}