From 10da23304ebc94e4cf26dc1a6a0a3ac889833a00 Mon Sep 17 00:00:00 2001 From: Brummel Date: Tue, 2 Jun 2026 02:19:35 +0200 Subject: [PATCH] refactor(prose): fold the five copies of effects-clause rendering into one helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The " with , " effects clause was rendered by five verbatim blocks across the fn / class-method / instance-method / type writers. Hoisted into write_effects_clause(out, effects); all five sites now call it. Output is byte-identical — the snapshot/round-trip tests confirm no drift. The two forall<...> blocks were left alone: they diverge in the trailing token (one ends `>`, the other `> ` before a where-clause), so a shared helper would be awkward rather than cleaner. --- crates/ailang-prose/src/lib.rs | 72 ++++++++++++---------------------- 1 file changed, 24 insertions(+), 48 deletions(-) diff --git a/crates/ailang-prose/src/lib.rs b/crates/ailang-prose/src/lib.rs index 6ca2ca1..64715f4 100644 --- a/crates/ailang-prose/src/lib.rs +++ b/crates/ailang-prose/src/lib.rs @@ -303,18 +303,7 @@ fn write_fn_def(out: &mut String, fd: &FnDef, level: usize, owning_module: &str) } out.push_str(") -> "); write_mode_type(out, ret, *ret_mode, owning_module); - if !effects.is_empty() { - out.push_str(" with "); - // Stable order: as written in the AST. Effects are - // semantically a set, but re-sorting would erase - // author-asserted ordering; preserve the AST order. - for (i, e) in effects.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - out.push_str(e); - } - } + write_effects_clause(out, effects); } else { // Defensive fallback: a non-Fn fn-type. Render the bare type so // nothing crashes; this path is unreachable for typechecked @@ -389,15 +378,7 @@ fn write_class_method(out: &mut String, m: &ClassMethod, level: usize, owning_mo } out.push_str(") -> "); write_mode_type(out, ret, *ret_mode, owning_module); - if !effects.is_empty() { - out.push_str(" with "); - for (i, e) in effects.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - out.push_str(e); - } - } + write_effects_clause(out, effects); } else { // Defensive fallback: a non-Fn class-method type. Render the // bare type so nothing crashes; this path is unreachable for @@ -451,6 +432,25 @@ fn write_instance_method(out: &mut String, m: &InstanceMethod, level: usize, own // ---- types ---------------------------------------------------------------- +/// Render the trailing effects clause of a fn / method / lambda signature. +/// +/// Emits nothing for an empty effect set; otherwise ` with ` followed by +/// the comma-separated effect names in AST order. Effects are +/// semantically a set, but re-sorting would erase author-asserted +/// ordering, so the AST order is preserved verbatim. +fn write_effects_clause(out: &mut String, effects: &[String]) { + if effects.is_empty() { + return; + } + out.push_str(" with "); + for (i, e) in effects.iter().enumerate() { + if i > 0 { + out.push_str(", "); + } + out.push_str(e); + } +} + fn write_mode_type(out: &mut String, t: &Type, mode: ParamMode, owning_module: &str) { match mode { ParamMode::Own => { @@ -511,15 +511,7 @@ fn write_type(out: &mut String, t: &Type, owning_module: &str) { } out.push_str(") -> "); write_mode_type(out, ret, *ret_mode, owning_module); - if !effects.is_empty() { - out.push_str(" with "); - for (i, e) in effects.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - out.push_str(e); - } - } + write_effects_clause(out, effects); } Type::Forall { vars, constraints: _, body } => { out.push_str("forall<"); @@ -742,15 +734,7 @@ fn write_term_prec(out: &mut String, t: &Term, level: usize, parent_prec: u8, ow } out.push_str(") -> "); write_mode_type(out, ret, *ret_mode, owning_module); - if !effects.is_empty() { - out.push_str(" with "); - for (i, e) in effects.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - out.push_str(e); - } - } + write_effects_clause(out, effects); } else { out.push_str(") -> "); write_type(out, ty, owning_module); @@ -853,15 +837,7 @@ fn write_term_prec(out: &mut String, t: &Term, level: usize, parent_prec: u8, ow } out.push_str("| -> "); write_type(out, ret_ty, owning_module); - if !effects.is_empty() { - out.push_str(" with "); - for (i, e) in effects.iter().enumerate() { - if i > 0 { - out.push_str(", "); - } - out.push_str(e); - } - } + write_effects_clause(out, effects); out.push_str(" {\n"); indent(out, level + 1); write_term(out, body, level + 1, owning_module);