iter revert: back out the Iteration-discipline milestone (it.1 + it.2)
One forward iteration; main never rewound.1ff7e81(the pre-9973546 commit) is the per-region byte oracle — every reverted source/test file is byte-identical to it; crates/ailang-check/src/lib.rs fully so. Root cause being corrected: the Iteration-discipline milestone was an over-escalation of fieldtest finding F1 (a [friction] item whose own minimal recommendation was a DESIGN.md note). Its totality dichotomy made the maximally-LLM-natural build(d:Int)=Node(1,build(d-1), build(d-1)) inexpressible (it.3 BLOCKED); the only in-thesis escape (A1/it.2b) conceded the language's first documented-unenforced totality precondition — a purity-pillar dilution the user rejected in favour of a full revert + rebuild. Removed: Term::Loop/Term::Recur/LoopBinder; the verify_structural_ recursion guardedness pass + term_contains_loop + Diverge-injection + the transitively-it.2 module_fns plumbing; the five Recur*/ NonStructuralRecursion CheckError variants (+ code() + the 3 dedicated ctx() arms); the it.1 codegen loop-header/phi/back-edge + parallel block_terminated setter; all Loop/Recur walker arms; 16 it.1/it.2 fixtures; 2 pin files; bench/it3-oracle/. Restored: 2 RC fixtures to1ff7e81content. Surgically kept (not in1ff7e81, landed with the milestone but independently sound): feature-acceptance clause 3 in DESIGN.md and skills/brainstorm/SKILL.md, with its worked example de-claimed from "shipped" to hypothetical-illustration form; the F3 P2 todo. bench/orchestrator-stats/2026-05-15-iter-it.{1,2,3}.json kept as historical record (like journals/plans). Sole net addition: an honest F1/F4 documented-idiom note in DESIGN.md (the tail-recursive accumulator fallback; examples/mut_counter.ail), guarded by a doc-presence test — "a documentation note is not a reshape", asserts nothing at the typecheck level. Roadmap: the Iteration-discipline block + blocking-fork section removed; the genuine total-Int-recursion ambition preserved as a deferred P2 milestone sequenced behind a future Nat/refinement-types milestone (not abandoned — correctly sequenced after the type machinery it needs). 2026-05-15-iteration-discipline.md carries a superseded header; it.1/it.2/it.3 journals + plans stay as history. Correctness gate PRISTINE: 164 surviving 1ff7e81-era fixtures ail check/ail run byte-identical to pre-milestone behaviour (verified against a1ff7e81worktree reference compiler, zero drift); cargo test --workspace 600/0; zero residual it.1/it.2 production surface. Spec docs/specs/2026-05-16-iteration-discipline-revert.md (b3853bf), plan docs/plans/2026-05-16-iter-revert.md (abf0013).
This commit is contained in:
@@ -343,7 +343,6 @@ mod tests {
|
||||
install(&mut env);
|
||||
let mut locals: IndexMap<String, Type> = IndexMap::new();
|
||||
let mut mut_scope_stack: Vec<IndexMap<String, Type>> = Vec::new();
|
||||
let mut loop_stack: Vec<Vec<Type>> = Vec::new();
|
||||
let mut effects: BTreeSet<String> = BTreeSet::new();
|
||||
let mut subst = Subst::default();
|
||||
let mut counter: u32 = 0;
|
||||
@@ -355,7 +354,6 @@ mod tests {
|
||||
&env,
|
||||
&mut locals,
|
||||
&mut mut_scope_stack,
|
||||
&mut loop_stack,
|
||||
&mut effects,
|
||||
"<test>",
|
||||
&mut subst,
|
||||
@@ -588,7 +586,6 @@ mod tests {
|
||||
install(&mut env);
|
||||
let mut locals: IndexMap<String, Type> = IndexMap::new();
|
||||
let mut mut_scope_stack: Vec<IndexMap<String, Type>> = Vec::new();
|
||||
let mut loop_stack: Vec<Vec<Type>> = Vec::new();
|
||||
let mut effects: BTreeSet<String> = BTreeSet::new();
|
||||
let mut subst = Subst::default();
|
||||
let mut counter: u32 = 0;
|
||||
@@ -600,7 +597,6 @@ mod tests {
|
||||
&env,
|
||||
&mut locals,
|
||||
&mut mut_scope_stack,
|
||||
&mut loop_stack,
|
||||
&mut effects,
|
||||
"<test>",
|
||||
&mut subst,
|
||||
|
||||
+33
-1024
File diff suppressed because it is too large
Load Diff
@@ -397,25 +397,6 @@ impl<'a> Lifter<'a> {
|
||||
name: name.clone(),
|
||||
value: Box::new(self.lift_in_term(value, locals, in_def)?),
|
||||
}),
|
||||
Term::Loop { binders, body } => Ok(Term::Loop {
|
||||
binders: binders
|
||||
.iter()
|
||||
.map(|b| {
|
||||
Ok(ailang_core::ast::LoopBinder {
|
||||
name: b.name.clone(),
|
||||
ty: b.ty.clone(),
|
||||
init: Box::new(self.lift_in_term(&b.init, locals, in_def)?),
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?,
|
||||
body: Box::new(self.lift_in_term(body, locals, in_def)?),
|
||||
}),
|
||||
Term::Recur { args } => Ok(Term::Recur {
|
||||
args: args
|
||||
.iter()
|
||||
.map(|a| self.lift_in_term(a, locals, in_def))
|
||||
.collect::<Result<Vec<_>>>()?,
|
||||
}),
|
||||
Term::LetRec { name, ty, params, body, in_term } => {
|
||||
// Iter 16b.3: post-order traversal — lift any inner
|
||||
// LetRecs first. Within the body's scope, `name` and
|
||||
@@ -743,11 +724,7 @@ impl<'a> Lifter<'a> {
|
||||
// term at a time, beginning from a top-of-body position; fresh
|
||||
// empty mut-scope stack is correct.
|
||||
let mut mut_scope_stack: Vec<indexmap::IndexMap<String, crate::Type>> = Vec::new();
|
||||
// Iter it.1 (DD-1): lift's letrec-capture re-entry walks one
|
||||
// term from a top-of-body position; fresh empty loop_stack is
|
||||
// correct (a loop captured into a letrec carries its own).
|
||||
let mut loop_stack: Vec<Vec<crate::Type>> = Vec::new();
|
||||
let ty = synth(t, &self.env, locals, &mut mut_scope_stack, &mut loop_stack, &mut effects, in_def, &mut subst, &mut counter, &mut residuals, &mut free_fn_calls, &mut warnings_discarded)?;
|
||||
let ty = synth(t, &self.env, locals, &mut mut_scope_stack, &mut effects, in_def, &mut subst, &mut counter, &mut residuals, &mut free_fn_calls, &mut warnings_discarded)?;
|
||||
Ok(subst.apply(&ty))
|
||||
}
|
||||
}
|
||||
@@ -784,10 +761,6 @@ fn contains_any_letrec(m: &Module) -> bool {
|
||||
vars.iter().any(|v| term_has_letrec(&v.init)) || term_has_letrec(body)
|
||||
}
|
||||
Term::Assign { value, .. } => term_has_letrec(value),
|
||||
Term::Loop { binders, body } => {
|
||||
binders.iter().any(|b| term_has_letrec(&b.init)) || term_has_letrec(body)
|
||||
}
|
||||
Term::Recur { args } => args.iter().any(term_has_letrec),
|
||||
}
|
||||
}
|
||||
for def in &m.defs {
|
||||
|
||||
@@ -609,17 +609,6 @@ impl<'a> Checker<'a> {
|
||||
// a tracked binder). Walk the `value` normally.
|
||||
self.walk(value, Position::Consume);
|
||||
}
|
||||
Term::Loop { binders, body } => {
|
||||
for b in binders {
|
||||
self.walk(&b.init, Position::Consume);
|
||||
}
|
||||
self.walk(body, pos);
|
||||
}
|
||||
Term::Recur { args } => {
|
||||
for a in args {
|
||||
self.walk(a, Position::Consume);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,8 +795,6 @@ fn make_reuse_as_source_not_bare_var(def: &str, source: &Term, body: &Term) -> D
|
||||
Term::ReuseAs { .. } => "reuse-as",
|
||||
Term::Mut { .. } => "mut",
|
||||
Term::Assign { .. } => "assign",
|
||||
Term::Loop { .. } => "loop",
|
||||
Term::Recur { .. } => "recur",
|
||||
};
|
||||
let replacement = term_to_form_a(body);
|
||||
Diagnostic::error(
|
||||
@@ -947,17 +934,6 @@ fn any_sub_binder_consumed_for(
|
||||
Term::Assign { value, .. } => {
|
||||
any_sub_binder_consumed_for(value, pname, uniq, def_name, ctors)
|
||||
}
|
||||
// Iter it.1: loop binders are scalar like mut-vars; recurse
|
||||
// into children defensively so a genuine consume-of-`pname`
|
||||
// inside a binder init / body / recur arg still surfaces.
|
||||
Term::Loop { binders, body } => {
|
||||
binders.iter().any(|b| {
|
||||
any_sub_binder_consumed_for(&b.init, pname, uniq, def_name, ctors)
|
||||
}) || any_sub_binder_consumed_for(body, pname, uniq, def_name, ctors)
|
||||
}
|
||||
Term::Recur { args } => args
|
||||
.iter()
|
||||
.any(|a| any_sub_binder_consumed_for(a, pname, uniq, def_name, ctors)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -713,16 +713,11 @@ pub fn collect_mono_targets(
|
||||
// mut-scope, since any `Term::Mut` will push its own frame as the
|
||||
// walk descends.
|
||||
let mut mut_scope_stack: Vec<indexmap::IndexMap<String, crate::Type>> = Vec::new();
|
||||
// Iter it.1 (DD-1): mono re-synth from top-of-body — empty
|
||||
// loop_stack; any `Term::Loop` pushes its own frame as the walk
|
||||
// descends.
|
||||
let mut loop_stack: Vec<Vec<crate::Type>> = Vec::new();
|
||||
crate::synth(
|
||||
&f.body,
|
||||
&env,
|
||||
&mut locals,
|
||||
&mut mut_scope_stack,
|
||||
&mut loop_stack,
|
||||
&mut effects,
|
||||
&f.name,
|
||||
&mut subst,
|
||||
@@ -1244,17 +1239,6 @@ fn rewrite_mono_calls(
|
||||
Term::Assign { value, .. } => {
|
||||
rewrite_mono_calls(value, method_to_candidate_classes, poly_free_fns, poly_free_fn_ccounts, caller_module, ordered_targets, cursor, locals);
|
||||
}
|
||||
Term::Loop { binders, body } => {
|
||||
for b in binders.iter_mut() {
|
||||
rewrite_mono_calls(&mut b.init, method_to_candidate_classes, poly_free_fns, poly_free_fn_ccounts, caller_module, ordered_targets, cursor, locals);
|
||||
}
|
||||
rewrite_mono_calls(body, method_to_candidate_classes, poly_free_fns, poly_free_fn_ccounts, caller_module, ordered_targets, cursor, locals);
|
||||
}
|
||||
Term::Recur { args } => {
|
||||
for a in args.iter_mut() {
|
||||
rewrite_mono_calls(a, method_to_candidate_classes, poly_free_fns, poly_free_fn_ccounts, caller_module, ordered_targets, cursor, locals);
|
||||
}
|
||||
}
|
||||
Term::Lit { .. } => {}
|
||||
}
|
||||
}
|
||||
@@ -1359,14 +1343,11 @@ pub(crate) fn collect_residuals_ordered(
|
||||
// mut-scope, since any `Term::Mut` will push its own frame as the
|
||||
// walk descends.
|
||||
let mut mut_scope_stack: Vec<indexmap::IndexMap<String, crate::Type>> = Vec::new();
|
||||
// Iter it.1 (DD-1): empty loop_stack at top-of-body re-synth.
|
||||
let mut loop_stack: Vec<Vec<crate::Type>> = Vec::new();
|
||||
crate::synth(
|
||||
&f.body,
|
||||
&env,
|
||||
&mut locals,
|
||||
&mut mut_scope_stack,
|
||||
&mut loop_stack,
|
||||
&mut effects,
|
||||
&f.name,
|
||||
&mut subst,
|
||||
@@ -1632,17 +1613,6 @@ fn interleave_slots(
|
||||
Term::Assign { value, .. } => {
|
||||
interleave_slots(value, method_to_candidate_classes, poly_free_fns, poly_free_fn_ccounts, class_slots, free_fn_slots, class_cur, free_cur, locals, out);
|
||||
}
|
||||
Term::Loop { binders, body } => {
|
||||
for b in binders {
|
||||
interleave_slots(&b.init, method_to_candidate_classes, poly_free_fns, poly_free_fn_ccounts, class_slots, free_fn_slots, class_cur, free_cur, locals, out);
|
||||
}
|
||||
interleave_slots(body, method_to_candidate_classes, poly_free_fns, poly_free_fn_ccounts, class_slots, free_fn_slots, class_cur, free_cur, locals, out);
|
||||
}
|
||||
Term::Recur { args } => {
|
||||
for a in args {
|
||||
interleave_slots(a, method_to_candidate_classes, poly_free_fns, poly_free_fn_ccounts, class_slots, free_fn_slots, class_cur, free_cur, locals, out);
|
||||
}
|
||||
}
|
||||
Term::Lit { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,18 +133,6 @@ fn walk_term(t: &Term) -> Result<(), CheckError> {
|
||||
walk_term(body)
|
||||
}
|
||||
Term::Assign { value, .. } => walk_term(value),
|
||||
Term::Loop { binders, body } => {
|
||||
for b in binders {
|
||||
walk_term(&b.init)?;
|
||||
}
|
||||
walk_term(body)
|
||||
}
|
||||
Term::Recur { args } => {
|
||||
for a in args {
|
||||
walk_term(a)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -265,17 +265,6 @@ impl<'a> Checker<'a> {
|
||||
self.walk(body);
|
||||
}
|
||||
Term::Assign { value, .. } => self.walk(value),
|
||||
Term::Loop { binders, body } => {
|
||||
for b in binders {
|
||||
self.walk(&b.init);
|
||||
}
|
||||
self.walk(body);
|
||||
}
|
||||
Term::Recur { args } => {
|
||||
for a in args {
|
||||
self.walk(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -352,17 +352,6 @@ impl<'a> Walker<'a> {
|
||||
Term::Assign { value, .. } => {
|
||||
self.walk(value, Position::Consume);
|
||||
}
|
||||
Term::Loop { binders, body } => {
|
||||
for b in binders {
|
||||
self.walk(&b.init, Position::Consume);
|
||||
}
|
||||
self.walk(body, pos);
|
||||
}
|
||||
Term::Recur { args } => {
|
||||
for a in args {
|
||||
self.walk(a, Position::Consume);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user