○
Planned This feature is planned but not yet implemented.
COMPILER BUG: Transitive purity cannot see .handler() calls
Code
// Test transitive impurity - pure calling impure = NOT transitively pure!
// Chain: compute (pure) -> log (IMPURE) -> result
// compute is marked ~[pure] but calls log (which does I/O)
// Therefore compute is locally pure but NOT transitively pure
const std = @import("std");
// Impure logging event (no ~[pure] annotation - does I/O)
~event log { msg: []const u8 }
| done {}
~proc log {
std.debug.print("[LOG] {s}\n", .{msg});
return .{ .done = .{} };
}
// Pure math operation
~event multiply { x: i32, factor: i32 }
| done { result: i32 }
~[pure]proc multiply {
return .{ .done = .{ .result = x * factor } };
}
// Marked pure but calls impure event - TAINTED!
~event compute_with_logging { x: i32 }
| done { result: i32 }
~[pure]proc compute_with_logging {
// Call impure log - this TAINTS our purity!
_ = log_event.handler(.{ .msg = "Computing..." });
const result = multiply_event.handler(.{ .x = x, .factor = 2 });
switch (result) {
.done => |d| {
return .{ .done = .{ .result = d.result } };
},
}
}
// Print result
~event print_number { n: i32 }
| done {}
~proc print_number {
std.debug.print("Result: {}\n", .{n});
return .{ .done = .{} };
}
// Main
~event main {}
| done {}
~proc main {
const result = compute_with_logging_event.handler(.{ .x = 21 });
switch (result) {
.done => |d| {
_ = print_number_event.handler(.{ .n = d.result });
},
}
return .{ .done = .{} };
}
~main()
| done |> _
Expected Output
[LOG] Computing...
Result: 42
Test Configuration
MUST_RUN
Post-validation Script:
#!/bin/bash
# Verify transitive impurity propagation
#
# Test expectations:
# - log: NOT marked ~[pure], does I/O → is_pure=false, is_transitively_pure=false
# - multiply: marked ~[pure], calls nothing → is_pure=true, is_transitively_pure=true
# - compute_with_logging: marked ~[pure], calls log (impure) → is_pure=true, is_transitively_pure=FALSE
if [ ! -f "backend.zig" ]; then
echo "✗ backend.zig not found"
exit 1
fi
# Check log proc - should be impure (not marked)
LOG_LINE=$(grep -n 'segments = @constCast(&\[_\]\[\]const u8{"log"})' backend.zig | \
tail -1 | cut -d: -f1)
if [ -z "$LOG_LINE" ]; then
echo "✗ Could not find log proc"
exit 1
fi
LOG_PROC=$(sed -n "${LOG_LINE},$((LOG_LINE + 20))p" backend.zig)
if echo "$LOG_PROC" | grep -q '.is_pure = false'; then
echo "✓ log: is_pure = false (not marked ~[pure])"
else
echo "✗ FAIL: log should be is_pure = false (unmarked proc)"
exit 1
fi
if echo "$LOG_PROC" | grep -q '.is_transitively_pure = false'; then
echo "✓ log: is_transitively_pure = false"
else
echo "✗ FAIL: log should be is_transitively_pure = false"
exit 1
fi
# Check multiply proc - should be pure
MULTIPLY_LINE=$(grep -n 'segments = @constCast(&\[_\]\[\]const u8{"multiply"})' backend.zig | \
tail -1 | cut -d: -f1)
if [ -z "$MULTIPLY_LINE" ]; then
echo "✗ Could not find multiply proc"
exit 1
fi
MULTIPLY_PROC=$(sed -n "${MULTIPLY_LINE},$((MULTIPLY_LINE + 20))p" backend.zig)
if echo "$MULTIPLY_PROC" | grep -q '.is_pure = true'; then
echo "✓ multiply: is_pure = true"
else
echo "✗ FAIL: multiply should be is_pure = true (marked ~[pure])"
exit 1
fi
if echo "$MULTIPLY_PROC" | grep -q '.is_transitively_pure = true'; then
echo "✓ multiply: is_transitively_pure = true (calls nothing)"
else
echo "✗ FAIL: multiply should be is_transitively_pure = true"
exit 1
fi
# Check compute_with_logging - locally pure but transitively impure!
COMPUTE_LINE=$(grep -n 'segments = @constCast(&\[_\]\[\]const u8{"compute_with_logging"})' backend.zig | \
tail -1 | cut -d: -f1)
if [ -z "$COMPUTE_LINE" ]; then
echo "✗ Could not find compute_with_logging proc"
exit 1
fi
COMPUTE_PROC=$(sed -n "${COMPUTE_LINE},$((COMPUTE_LINE + 20))p" backend.zig)
if echo "$COMPUTE_PROC" | grep -q '.is_pure = true'; then
echo "✓ compute_with_logging: is_pure = true (marked ~[pure])"
else
echo "✗ FAIL: compute_with_logging should be is_pure = true (marked ~[pure])"
exit 1
fi
if echo "$COMPUTE_PROC" | grep -q '.is_transitively_pure = false'; then
echo "✓ compute_with_logging: is_transitively_pure = FALSE (calls impure log)"
echo " ⚠️ TAINTED by impurity!"
else
echo "✗ FAIL: compute_with_logging should be is_transitively_pure = false"
echo " It calls log which is impure - transitive purity should be FALSE"
exit 1
fi
echo ""
echo "✓ Transitive impurity correctly propagates through call chains"
exit 0