iter ctt.3: KindMismatch retire

This commit is contained in:
2026-05-12 22:31:57 +02:00
parent 0e556f085c
commit 0d3f44bee1
6 changed files with 97 additions and 83 deletions
@@ -0,0 +1,12 @@
{
"iter_id": "ctt.3",
"date": "2026-05-12",
"mode": "standard",
"outcome": "DONE",
"tasks_total": 2,
"tasks_completed": 2,
"reloops_per_task": { "1": 0, "2": 0 },
"review_loops_spec": 0,
"review_loops_quality": 0,
"blocked_reason": null
}
-20
View File
@@ -1160,26 +1160,6 @@ fn workspace_error_to_diagnostic(
"method": method,
})),
),
W::KindMismatch {
class,
param,
method,
defining_module,
} => Some(
ailang_check::Diagnostic::error(
"kind-mismatch",
format!(
"kind mismatch in class `{class}`: parameter `{param}` is used in applied position \
inside method `{method}` (Decision 11 axis 5: class params are kind `*` only)"
),
)
.with_ctx(serde_json::json!({
"class": class,
"param": param,
"method": method,
"defining_module": defining_module,
})),
),
W::InvalidSuperclassParam {
class,
superclass,
+4 -1
View File
@@ -1425,9 +1425,12 @@ fn check_def(def: &Def, env: &Env) -> Result<()> {
Def::Const(c) => check_const(c, env),
Def::Type(td) => check_type_def(td, env),
// Iter 22b.1: schema-only landing for class/instance defs.
// Class-schema validation (KindMismatch, InvalidSuperclassParam,
// Class-schema validation (InvalidSuperclassParam,
// ConstraintReferencesUnboundTypeVar) and instance-body
// typechecking (with class-method substitution) land in 22b.2.
// ctt.3: KindMismatch retired — the malformed-class-param
// shape now fires BareCrossModuleTypeRef from the canonical-
// form validator instead.
// Workspace-load coherence checks (Orphan / Duplicate /
// MissingMethod) already fire from `workspace::build_registry`,
// so a malformed instance never reaches this point.
+6 -62
View File
@@ -253,22 +253,6 @@ pub enum WorkspaceLoadError {
method: String,
},
/// Iter 22b.2: class-schema validation. The class parameter
/// appears in applied position (e.g. as the head of a
/// `Type::Con { name == param, args.len() > 0 }`) inside a method
/// signature. Decision 11 axis 5 forbids HKTs — class params are
/// kind `*` only.
#[error(
"kind mismatch in class `{class}`: parameter `{param}` is used in applied position \
inside method `{method}` (Decision 11 axis 5: class params are kind `*` only)"
)]
KindMismatch {
class: String,
param: String,
method: String,
defining_module: String,
},
/// Iter 22b.2: class-schema validation. A class's `superclass.type`
/// does not equal its own `param`. Decision 11 single-superclass
/// model requires the superclass to be applied to the same param
@@ -789,23 +773,17 @@ fn build_registry(
}
/// Iter 22b.2: class-schema validation. Runs before `build_registry`.
/// Three diagnostics fire from here: `kind-mismatch`,
/// `invalid-superclass-param`, `constraint-references-unbound-type-var`.
/// Two diagnostics fire from here: `invalid-superclass-param`,
/// `constraint-references-unbound-type-var`. The `kind-mismatch`
/// diagnostic was retired at ctt.3 — the malformed shape now
/// fires `BareCrossModuleTypeRef` from the canonical-form
/// validator before `validate_classdefs` runs.
fn validate_classdefs(
modules: &BTreeMap<String, Module>,
) -> Result<(), WorkspaceLoadError> {
for (mod_name, m) in modules {
for m in modules.values() {
for def in &m.defs {
if let Def::Class(c) = def {
for method in &c.methods {
walk_kind_mismatch(&method.ty, &c.param)
.map_err(|()| WorkspaceLoadError::KindMismatch {
class: c.name.clone(),
param: c.param.clone(),
method: method.name.clone(),
defining_module: mod_name.clone(),
})?;
}
if let Some(sc) = &c.superclass {
if sc.type_ != c.param {
return Err(WorkspaceLoadError::InvalidSuperclassParam {
@@ -841,31 +819,6 @@ fn validate_classdefs(
Ok(())
}
/// Walks a `Type` looking for any `Type::Con { name == param, args
/// non-empty }`. The class param is kind `*`; appearing as a
/// constructor with arguments is a kind-mismatch.
fn walk_kind_mismatch(t: &Type, param: &str) -> Result<(), ()> {
match t {
Type::Con { name, args } => {
if name == param && !args.is_empty() {
return Err(());
}
for a in args {
walk_kind_mismatch(a, param)?;
}
Ok(())
}
Type::Fn { params, ret, .. } => {
for p in params {
walk_kind_mismatch(p, param)?;
}
walk_kind_mismatch(ret, param)
}
Type::Forall { body, .. } => walk_kind_mismatch(body, param),
Type::Var { .. } => Ok(()),
}
}
/// ct.1: the five primitive type names that are always bare under
/// the canonical-form rule. Kept in sync with `Type::int`,
/// `Type::bool_`, `Type::str_`, `Type::unit`, `Type::float` in
@@ -1876,15 +1829,6 @@ mod tests {
}
}
/// ct.1: a class whose parameter `f` appears as a `Type::Con`
/// name (the malformed-but-historically-test-fixture shape used
/// to trigger `KindMismatch` pre-ct.1) is now caught earlier by
/// the canonical-type-names validator: `f` is bare,
/// non-primitive, and not a TypeDef in the owning module, so
/// `BareCrossModuleTypeRef` fires before `validate_classdefs`
/// gets a chance to run. The `KindMismatch` path stays in the
/// codebase as dead-but-defensive code; a future tidy may
/// retire it.
#[test]
fn class_param_in_applied_position_fires_canonical_form_rejection() {
let entry = std::path::PathBuf::from(
+74
View File
@@ -0,0 +1,74 @@
# iter ctt.3 — `KindMismatch` retire (pure deletion across 3 files)
**Date:** 2026-05-12
**Started from:** 0e556f085c14993441b7d25dcdc69077b77c83b0
**Status:** DONE
**Tasks completed:** 2 of 2
## Summary
`WorkspaceLoadError::KindMismatch`, its dispatch site in
`validate_classdefs`, its `walk_kind_mismatch` helper, its Display
arm in `crates/ail/src/main.rs:workspace_error_to_diagnostic`, and
the "dead-but-defensive" doc-comment on the canonical-form-rejection
test are all retired. Two adjacent textual-consistency edits ride
along: the `validate_classdefs` doc-comment narrows from "Three
diagnostics fire from here" to "Two" with a successor sentence
naming the new path, and the `crates/ailang-check/src/lib.rs:1428`
22b.1-era archaeology comment drops the `KindMismatch` token from
its enumeration of class-schema diagnostics and gains a one-line
ctt.3 retirement marker. The existing test
`class_param_in_applied_position_fires_canonical_form_rejection`
stays green unchanged — it asserts `BareCrossModuleTypeRef` on the
malformed fixture, which is the canonical-form-validator successor
the plan named. `cargo build --workspace` clean, no orphan match
arms, no dead-code warnings. `cargo test --workspace` green
(~600 tests across 16 binary-test suites, zero failures).
## Per-task notes
- iter ctt.3.1: atomic deletion pass — 6 Edits across 3 files. workspace.rs ×4 (variant delete; `validate_classdefs` doc + dispatch-loop delete; `walk_kind_mismatch` helper delete; "dead-but-defensive" doc delete). main.rs ×1 (`W::KindMismatch` arm in `workspace_error_to_diagnostic`). lib.rs ×1 (22b.1 archaeology comment). Build green at Step 7.
- iter ctt.3.2: workspace-wide test gate — grep substantively clean in `crates/` (one residual `KindMismatch` token at lib.rs:1431 is the ctt.3 retirement marker introduced by Step 6 itself, not a live consumer); canonical-form-rejection test PASS; full `cargo test --workspace` PASS.
## Concerns
- Plan-internal contradiction surfaced during Task 2 Step 1: the
plan's Step 6 `new_string` deliberately introduces a new
`KindMismatch` token in the ctt.3 retirement marker
(`// ctt.3: KindMismatch retired — ...`), but Task 2 Step 1's
verification text says "Expected: zero hits in `crates/`". The
parent spec at `docs/specs/2026-05-12-ct-tidy.md:384` is more
permissive ("`grep KindMismatch` returns the three deletion sites
only" — accepting the diff itself as the only mention, but
silent on a successor archaeology marker). Substantive intent
(retire the diagnostic) is met: variant, helper, dispatch, and
Display arm are all gone. Treated as `compliant` with this
concern recorded; Boss may choose to either tighten the
spec/plan rule for future tidies or accept the retirement-marker
pattern (which is already common in the codebase — cf. ctt.1
successor-rationale comments in workspace.rs).
- Mid-deletion repair on workspace.rs:773 — the dispatch-loop
deletion in Step 2 orphaned the `mod_name` binding that
destructured `for (mod_name, m) in modules`. Plan Step 7's
acceptance criterion is "no dead-code warnings" — left as
`for (mod_name, m)` the build would warn `unused variable:
mod_name`. Minimal cleanup applied: rewrote to
`for m in modules.values()`. Same body, same `m: &Module` type
via `.values()` instead of tuple-destructure. Not in the plan's
verbatim edit list but a foreseeable side-effect of the
deletion and entirely mechanical.
## Known debt
- None new. The "future tidy may retire" promise in the deleted
doc-comment is now this iter; no successor obligation.
## Files touched
- `crates/ailang-core/src/workspace.rs` (variant delete + doc adjust + dispatch-loop delete + helper delete + test-doc delete + `mod_name` binding cleanup)
- `crates/ail/src/main.rs` (Display arm delete)
- `crates/ailang-check/src/lib.rs` (archaeology comment edit)
## Stats
bench/orchestrator-stats/2026-05-12-iter-ctt.3.json
+1
View File
@@ -39,3 +39,4 @@
- 2026-05-12 — audit-eob: milestone close (heap-str-abi) — architect drift fixed inline as `eob.tidy` (3 DESIGN.md edits: float_to_str / int_to_str caveats dropped, "Str ABI" anchor added documenting both heap-Str and static-Str realisations with their shared consumer ABI and codegen-level non-RC invariant for static-Str); bench mixed (latency.explicit_at_rc improvement cluster reappears for the 3rd consecutive audit + new marginal bump_s regressions on list_sum/hof_pipeline 12% over 10% tol), baseline pristine for 3rd consecutive audit (conservative call: latency cluster has no identified cause across 3 audits — ratify-without-attribution would obscure future signal; bump_s cluster is first-sighting, observe next audit) → 2026-05-12-audit-eob.md
- 2026-05-12 — iter ctt.1: env-overlay shape ratification — new DESIGN.md top-level section `## Env construction` anchors the `env.types` (owning) / `env.ctor_index` (reverse-index) split with the semantic rationale, plus the intentional check-side / mono-side asymmetry (mono-side narrowed at ct.3.2, check-side retains both halves because in-band `DuplicateCtor` consumes the per-module `env.ctor_index` rebuild); new behavioural-pin test `crates/ailang-check/tests/duplicate_ctor_pin.rs` ratifies the consumer; two P2 roadmap todos struck `[x]` (overlay shape question, per-module overlay narrowing); 3/3 tasks first-shot, zero review re-loops, no production-code edits → 2026-05-12-iter-ctt.1.md
- 2026-05-12 — iter ctt.2: `Registry.type_def_module` re-key from `BTreeMap<String, String>` to `BTreeMap<(String, String), String>` keyed by `(owning_module, bare_name)`; new `caller_module: &str` parameter threads through `normalize_type_for_registry` + `Registry::normalize_type_for_lookup`; four `ailang-check` consumer sites (lib.rs:1640, mono.rs:121/624/1175) pass the correct module-context (env.current_module / defining_module / module_name) per the plan's Design Notes; new regression test plus three-module fixture (`ctt2_collision_{cls,lib,main}.ail.json`) exercises the cross-module bare-name collision shape that pre-ctt.2 silently overwrote; RED-failure observed as `OrphanInstance` rather than the plan's predicted `DuplicateInstance` because the pass-2 coherence check (workspace.rs:656-659) is also a bare-name consumer and fires earlier; both consumers fixed by the same re-key; plan's verbatim two-module fixture had two structural defects (two-way imports → Cycle, qualified `InstanceDef.class` → QualifiedClassName) that the implementer-phase repair handled by introducing the third cls-module; spec-intent (RED-first against bare-name collision) preserved; `cargo test --workspace` green (16 binary-test suites, ~600 tests, zero failures) → 2026-05-12-iter-ctt.2.md
- 2026-05-12 — iter ctt.3: `KindMismatch` retire — pure deletion across 3 files (workspace.rs: variant + dispatch + helper + "dead-but-defensive" doc; main.rs: Display arm; lib.rs: 22b.1 archaeology comment). Existing test `class_param_in_applied_position_fires_canonical_form_rejection` stays green unchanged (asserts `BareCrossModuleTypeRef` on the malformed fixture — the canonical-form-validator successor path). Two adjacent textual-consistency edits ride along (validate_classdefs doc-comment "Three → Two", lib.rs archaeology comment gains a ctt.3 retirement marker). One mid-deletion mechanical fix: dispatch-loop deletion orphaned `mod_name` binding → rewrote `for (mod_name, m) in modules` to `for m in modules.values()` (same body type, mechanical). 2/2 tasks, ~600 tests green across 16 binary-test suites → 2026-05-12-iter-ctt.3.md