mirror of
https://github.com/typst/typst
synced 2025-05-21 12:35:29 +08:00
Fix missing capturing of assignments
The previous commit was a bit overambitious. The left-hand side of assignments should actually be fully captured: Argument lists in `at` calls can contain captured variables. And if the assigned variable itself is captured, then the function is faulty anyway. (And we ensure the correct error message by capturing it.) Fixes #2169
This commit is contained in:
parent
b7430f6da0
commit
25613cfaf3
@ -1440,18 +1440,6 @@ impl BinOp {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this is an assignment operator.
|
|
||||||
pub fn is_assignment(self) -> bool {
|
|
||||||
matches!(
|
|
||||||
self,
|
|
||||||
Self::Assign
|
|
||||||
| Self::AddAssign
|
|
||||||
| Self::SubAssign
|
|
||||||
| Self::MulAssign
|
|
||||||
| Self::DivAssign
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The precedence of this operator.
|
/// The precedence of this operator.
|
||||||
pub fn precedence(self) -> usize {
|
pub fn precedence(self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
|
@ -688,16 +688,6 @@ impl<'a> CapturesVisitor<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't capture left-hand side of an assignment.
|
|
||||||
Some(ast::Expr::Binary(binary)) if binary.op().is_assignment() => {
|
|
||||||
self.visit(binary.rhs().to_untyped());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't capture the left-hand side of a destructuring assignment.
|
|
||||||
Some(ast::Expr::DestructAssign(assignment)) => {
|
|
||||||
self.visit(assignment.value().to_untyped());
|
|
||||||
}
|
|
||||||
|
|
||||||
// A for loop contains one or two bindings in its pattern. These are
|
// A for loop contains one or two bindings in its pattern. These are
|
||||||
// active after the iterable is evaluated but before the body is
|
// active after the iterable is evaluated but before the body is
|
||||||
// evaluated.
|
// evaluated.
|
||||||
@ -828,5 +818,6 @@ mod tests {
|
|||||||
test("#(body = 1)", &[]);
|
test("#(body = 1)", &[]);
|
||||||
test("#(body += y)", &["y"]);
|
test("#(body += y)", &["y"]);
|
||||||
test("#{ (body, a) = (y, 1) }", &["y"]);
|
test("#{ (body, a) = (y, 1) }", &["y"]);
|
||||||
|
test("#(x.at(y) = 5)", &["x", "y"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,24 @@
|
|||||||
f(1, "two", () => x)
|
f(1, "two", () => x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
// Mutable method with capture in argument.
|
||||||
|
#let x = "b"
|
||||||
|
#let f() = {
|
||||||
|
let a = (b: 5)
|
||||||
|
a.at(x) = 10
|
||||||
|
a
|
||||||
|
}
|
||||||
|
#f()
|
||||||
|
|
||||||
|
---
|
||||||
|
#let x = ()
|
||||||
|
#let f() = {
|
||||||
|
// Error: 3-4 variables from outside the function are read-only and cannot be modified
|
||||||
|
x.at(1) = 2
|
||||||
|
}
|
||||||
|
#f()
|
||||||
|
|
||||||
---
|
---
|
||||||
// Named arguments.
|
// Named arguments.
|
||||||
#{
|
#{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user