From e3bfc01027058c1e9860a1267669103aa5fa9467 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Sun, 22 Feb 2026 09:20:44 +0100 Subject: [PATCH] Fix: Correctly determine lambda purity The purity of a lambda definition should always be `Pure`. The purity of the lambda's body is only relevant when the lambda is called. This change ensures that defining a lambda does not incorrectly mark the parent scope as impure. --- src/ast/compiler/optimizer.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/ast/compiler/optimizer.rs b/src/ast/compiler/optimizer.rs index 9fab411..7c008d6 100644 --- a/src/ast/compiler/optimizer.rs +++ b/src/ast/compiler/optimizer.rs @@ -691,7 +691,8 @@ impl Optimizer { fn purity_of(&self, node: &TypedNode) -> Purity { match &node.kind { BoundKind::Constant(_) | BoundKind::Parameter { .. } | BoundKind::Nop => Purity::Pure, - BoundKind::Lambda { body, .. } => self.purity_of(body), + // Defining a lambda is pure; only calling it may have side effects. + BoundKind::Lambda { .. } => Purity::Pure, BoundKind::Get { addr, .. } => match addr { Address::Global(idx) => { if let Some(purity_rc) = &self.global_purity { @@ -734,6 +735,7 @@ impl Optimizer { BoundKind::Set { .. } => Purity::Impure, BoundKind::Call { callee, args } => { let callee_purity = match &callee.kind { + BoundKind::Lambda { body, .. } => self.purity_of(body), BoundKind::Get { addr: Address::Global(idx), .. @@ -1365,4 +1367,19 @@ mod tests { ); assert!(dump.contains("Constant: 42")); } + + #[test] + fn test_opt_unused_lambda_with_side_effects_dce() { + // Die Lambda-Definition selbst ist Pure, auch wenn ihr Body Impure ist (assign). + // Daher muss sie gelöscht werden, wenn sie nicht gerufen wird. + // 'g' muss definiert sein, damit der Binder nicht abbricht. + let source = "(fn [] (do (def g 0) (def f (fn [x] (assign g 1))) 42))"; + let dump = get_optimized_dump(source, true); + assert!( + !dump.contains("DefLocal (Name: 'f'"), + "Unused lambda with side effects should be removed by DCE. Dump: \n{}", + dump + ); + assert!(dump.contains("Constant: 42")); + } }