From 21d821e3718fab8a4a3e99edd3e8a4891e8951f0 Mon Sep 17 00:00:00 2001 From: Brummel Date: Thu, 14 May 2026 02:19:05 +0200 Subject: [PATCH] iter rpe.1.tidy: subst.rs preserves Type::Fn modes through rebuild MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes audit-rpe.1's [medium] drift: qualify_local_types_codegen and apply_subst_to_type at crates/ailang-codegen/src/subst.rs:188 + :217 both carried the field-spread Type::Fn rebuild shape that strips param_modes and ret_mode to vec![] / ParamMode::Implicit. Symmetric to the feb9413 substitute_rigids fix flagged in that commit's message as a bug class. Fix: bind param_modes and ret_mode in the destructure, thread them through unchanged. cargo test --workspace 564/0/3; clippy + doc zero warnings. Audit-rpe.1's [nit] dead Emitter.strings field deferred as known-debt — it cycles over an empty map harmlessly. Three other field-spread Type::Fn rebuild sites in ailang-check/src/lib.rs and lift.rs follow the same pattern but are not currently flagged by failing tests; left in place pending correctness-reachability verification per the journal Known debt section. --- crates/ailang-codegen/src/subst.rs | 12 ++--- docs/journals/2026-05-14-iter-rpe.1.tidy.md | 58 +++++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 docs/journals/2026-05-14-iter-rpe.1.tidy.md diff --git a/crates/ailang-codegen/src/subst.rs b/crates/ailang-codegen/src/subst.rs index de4c20b..8757158 100644 --- a/crates/ailang-codegen/src/subst.rs +++ b/crates/ailang-codegen/src/subst.rs @@ -185,15 +185,15 @@ pub(crate) fn qualify_local_types_codegen( .collect(), } } - Type::Fn { params, ret, effects, .. } => Type::Fn { + Type::Fn { params, ret, effects, param_modes, ret_mode } => Type::Fn { params: params .iter() .map(|p| qualify_local_types_codegen(p, owner_module, owner_local_types)) .collect(), ret: Box::new(qualify_local_types_codegen(ret, owner_module, owner_local_types)), effects: effects.clone(), - param_modes: vec![], - ret_mode: ParamMode::Implicit, + param_modes: param_modes.clone(), + ret_mode: *ret_mode, }, Type::Forall { vars, constraints, body } => Type::Forall { vars: vars.clone(), @@ -214,12 +214,12 @@ pub(crate) fn apply_subst_to_type(t: &Type, subst: &BTreeMap) -> T name: name.clone(), args: args.iter().map(|a| apply_subst_to_type(a, subst)).collect(), }, - Type::Fn { params, ret, effects, .. } => Type::Fn { + Type::Fn { params, ret, effects, param_modes, ret_mode } => Type::Fn { params: params.iter().map(|p| apply_subst_to_type(p, subst)).collect(), ret: Box::new(apply_subst_to_type(ret, subst)), effects: effects.clone(), - param_modes: vec![], - ret_mode: ParamMode::Implicit, + param_modes: param_modes.clone(), + ret_mode: *ret_mode, }, Type::Forall { vars, constraints, body } => { // Inner forall shadows: don't substitute re-bound names. diff --git a/docs/journals/2026-05-14-iter-rpe.1.tidy.md b/docs/journals/2026-05-14-iter-rpe.1.tidy.md new file mode 100644 index 0000000..eb47eb4 --- /dev/null +++ b/docs/journals/2026-05-14-iter-rpe.1.tidy.md @@ -0,0 +1,58 @@ +# iter rpe.1.tidy — Close audit-rpe.1 [medium] drift + +**Date:** 2026-05-14 +**Started from:** 973f50b (post-rpe.1 + audit-rpe.1) +**Status:** DONE + +## Summary + +Closes the single `[medium]` drift item surfaced by audit-rpe.1: +`crates/ailang-codegen/src/subst.rs:188,217` — `qualify_local_types_codegen` +and `apply_subst_to_type` both carried the exact +`Type::Fn { params, ret, effects, .. }` field-spread that drops +`param_modes` and `ret_mode` to `vec![]` / `ParamMode::Implicit`. This +is the same shape the print-leak bugfix at commit feb9413 corrected +in `crates/ailang-check/src/lib.rs::substitute_rigids`, and the +feb9413 commit message explicitly flagged any other instance as a +latent bug in the same class. + +Fix: preserve both fields through the rebuild — `param_modes.clone()` +(it's a `Vec`) and `*ret_mode` (Copy). Symmetric to the feb9413 fix. + +The audit's `[nit]` finding (dead `Emitter.strings` field in +`crates/ailang-codegen/src/lib.rs`, an orphan after `intern_string` +was removed in rpe.1 Task 4) is left as a follow-up tidy candidate — +it cycles over an empty map harmlessly and isn't an audit gate. + +## Files touched + +- `crates/ailang-codegen/src/subst.rs:188` — + `qualify_local_types_codegen` Type::Fn arm now binds + `param_modes` and `ret_mode` and threads them through. +- `crates/ailang-codegen/src/subst.rs:217` — + `apply_subst_to_type` Type::Fn arm same shape. + +## Verification + +- `cargo test --workspace` → 564 / 0 / 3 (baseline holds). +- `cargo clippy --workspace --all-targets` → 0 warnings. +- `cargo doc --workspace --no-deps` → 0 warnings. + +## Concerns + +- (none) + +## Known debt + +- `Emitter.strings` field in `crates/ailang-codegen/src/lib.rs` + remains dead. Cycles over empty map; no behavioural impact. + Roll into a future opportunistic cleanup. +- Three other field-spread `Type::Fn` rebuild sites + (`crates/ailang-check/src/lib.rs:93` and `:3492`, + `crates/ailang-check/src/lift.rs:875`) ALSO drop `param_modes` + / `ret_mode` to `vec![]` / `Implicit`. They were not flagged + by audit-rpe.1 because no currently-failing test pins them. + Leaving conservatively in place — a flag for a future + fieldtest or audit cycle. The pattern of field-spread-and- + drop is the bug class; whether each site is correctness- + reachable is what needs verification before changing.