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.
This commit is contained in:
@@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user