forked from M-Labs/artiq
compiler: disallow op= on mutable values (fix #835).
In general, we can't reallocate a value in earlier stack frames, or fixup references to it. This mainly impacts lists.
This commit is contained in:
parent
f86744c65c
commit
e59b301a3b
|
@ -298,8 +298,8 @@ class EscapeValidator(algorithm.Visitor):
|
||||||
# and exceptions can only refer to strings, so we don't actually check
|
# and exceptions can only refer to strings, so we don't actually check
|
||||||
# this property. But we will need to, if string operations are ever added.
|
# this property. But we will need to, if string operations are ever added.
|
||||||
|
|
||||||
def visit_assignment(self, target, value, is_aug_assign=False):
|
def visit_assignment(self, target, value):
|
||||||
value_region = self._region_of(value) if not is_aug_assign else self.youngest_region
|
value_region = self._region_of(value)
|
||||||
|
|
||||||
# If this is a variable, we might need to contract the live range.
|
# If this is a variable, we might need to contract the live range.
|
||||||
if isinstance(value_region, Region):
|
if isinstance(value_region, Region):
|
||||||
|
@ -316,19 +316,11 @@ class EscapeValidator(algorithm.Visitor):
|
||||||
target_regions = [self._region_of(name) for name in target_names]
|
target_regions = [self._region_of(name) for name in target_names]
|
||||||
for target_region in target_regions:
|
for target_region in target_regions:
|
||||||
if not Region.outlives(value_region, target_region):
|
if not Region.outlives(value_region, target_region):
|
||||||
if is_aug_assign:
|
|
||||||
target_desc = "the assignment target, allocated here,"
|
|
||||||
else:
|
|
||||||
target_desc = "the assignment target"
|
|
||||||
note = diagnostic.Diagnostic("note",
|
|
||||||
"this expression has type {type}",
|
|
||||||
{"type": types.TypePrinter().name(value.type)},
|
|
||||||
value.loc)
|
|
||||||
diag = diagnostic.Diagnostic("error",
|
diag = diagnostic.Diagnostic("error",
|
||||||
"the assigned value does not outlive the assignment target", {},
|
"the assigned value does not outlive the assignment target", {},
|
||||||
value.loc, [target.loc],
|
value.loc, [target.loc],
|
||||||
notes=self._diagnostics_for(target_region, target.loc,
|
notes=self._diagnostics_for(target_region, target.loc,
|
||||||
target_desc) +
|
"the assignment target") +
|
||||||
self._diagnostics_for(value_region, value.loc,
|
self._diagnostics_for(value_region, value.loc,
|
||||||
"the assigned value"))
|
"the assigned value"))
|
||||||
self.engine.process(diag)
|
self.engine.process(diag)
|
||||||
|
@ -339,9 +331,19 @@ class EscapeValidator(algorithm.Visitor):
|
||||||
|
|
||||||
def visit_AugAssign(self, node):
|
def visit_AugAssign(self, node):
|
||||||
if builtins.is_allocated(node.target.type):
|
if builtins.is_allocated(node.target.type):
|
||||||
# If the target is mutable, op-assignment will allocate
|
note = diagnostic.Diagnostic("note",
|
||||||
# in the youngest region.
|
"try using `{lhs} = {lhs} {op} {rhs}` instead",
|
||||||
self.visit_assignment(node.target, node.value, is_aug_assign=True)
|
{"lhs": node.target.loc.source(),
|
||||||
|
"rhs": node.value.loc.source(),
|
||||||
|
"op": node.op.loc.source()[:-1]},
|
||||||
|
node.loc)
|
||||||
|
diag = diagnostic.Diagnostic("error",
|
||||||
|
"values cannot be mutated in-place", {},
|
||||||
|
node.op.loc, [node.target.loc],
|
||||||
|
notes=[note])
|
||||||
|
self.engine.process(diag)
|
||||||
|
|
||||||
|
self.visit_assignment(node.target, node.value)
|
||||||
|
|
||||||
def visit_Return(self, node):
|
def visit_Return(self, node):
|
||||||
region = self._region_of(node.value)
|
region = self._region_of(node.value)
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
|
from artiq.experiment import *
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def entrypoint():
|
||||||
|
a = [1,2]
|
||||||
|
# CHECK-L: ${LINE:+2}: error: values cannot be mutated in-place
|
||||||
|
# CHECK-L: ${LINE:+1}: note: try using `a = a + [3,4]`
|
||||||
|
a += [3,4]
|
||||||
|
|
Loading…
Reference in New Issue