iter rpe.1.tidy: subst.rs preserves Type::Fn modes through rebuild
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.
This commit is contained in:
@@ -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<String, Type>) -> 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.
|
||||
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user