V2041 assign_captured_var
A lambda, or a try body, assigns to a var declared outside it.
An error from the type phase. sakura explain V2041 prints this explanation offline.
A lambda, or a try body, assigns to a var declared outside it. Closures capture vars by
value, so the assignment would be lost (design §8.1); a try body's only outputs are its value
and its error (design §5.3). Use a loop with the var in the same function, or return the new
value and assign it afterwards.
Wrong:
var n = 0
let r = try { n = parse(s)? }Fixed:
var n = 0
let r = try { parse(s)? }
n = r.unwrap_or(0)Wrong program
compiler/tests/ui/V2041_assign_captured_var.sakura, which the compiler's ui suite runs through sakura check:
fn total() -> Int {
var sum = 0
let add = fn(x) { sum = sum + x }
add(1)
sum
}sakura check --json reports this record (pretty-printed; $DIR is the fixture's directory):
{
"schema_version": "1.0",
"kind": "diagnostic",
"id": "d:c2398541ac6c660a",
"code": "V2041",
"severity": "error",
"phase": "type",
"message": "this function value assigns `sum`, a `var` of the enclosing function; closures capture variables by value, so the assignment would be lost",
"snapshot": "sha256:$SNAPSHOT",
"symbol_id": "main::V2041_assign_captured_var::total",
"spans": [
{
"uri": "file://$DIR/V2041_assign_captured_var.sakura",
"content_hash": "sha256:97a19a1223e83309a662c4808f5fc8387a02dbebe4f7ad50d975c397cf561e6d",
"start_byte": 88,
"end_byte": 101,
"role": "primary"
}
],
"related_ids": [],
"expected": null,
"actual": null,
"obligation": null,
"counterexample": null,
"explanation_uri": "sakura://explain/V2041",
"fixes": []
}More fixtures for this code: compiler/tests/ui/V2041_assign_in_try.sakura.
Fixed program
compiler/tests/ui/V2041_assign_captured_var.fixed.sakura, which sakura check accepts with no diagnostics:
fn total() -> Int {
var sum = 0
for x in [1] { sum = sum + x }
sum
}