refactor(prose): fold the five copies of effects-clause rendering into one helper

The " with <e1>, <e2>" 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.
This commit is contained in:
2026-06-02 02:19:35 +02:00
parent 9b0eb58cd9
commit 10da23304e
+24 -48
View File
@@ -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);