Adjust for-loop's pattern matching rules (#3308)
This commit is contained in:
parent
ce5abf5a4e
commit
51854ba4df
@ -108,11 +108,11 @@ impl Eval for ast::ForLoop<'_> {
|
||||
let mut output = Value::None;
|
||||
|
||||
macro_rules! iter {
|
||||
(for $pat:ident in $iter:expr) => {{
|
||||
(for $pat:ident in $iterable:expr) => {{
|
||||
vm.scopes.enter();
|
||||
|
||||
#[allow(unused_parens)]
|
||||
for value in $iter {
|
||||
for value in $iterable {
|
||||
destructure(vm, $pat, value.into_value())?;
|
||||
|
||||
let body = self.body();
|
||||
@ -134,29 +134,30 @@ impl Eval for ast::ForLoop<'_> {
|
||||
}};
|
||||
}
|
||||
|
||||
let pattern = self.pattern();
|
||||
let iterable = self.iterable().eval(vm)?;
|
||||
let iterable_type = iterable.ty();
|
||||
let pattern = self.pattern();
|
||||
|
||||
match (&pattern, iterable) {
|
||||
(ast::Pattern::Normal(_), Value::Str(string)) => {
|
||||
// Iterate over graphemes of string.
|
||||
iter!(for pattern in string.as_str().graphemes(true));
|
||||
use ast::Pattern;
|
||||
match (pattern, iterable) {
|
||||
(_, Value::Array(array)) => {
|
||||
// Iterate over values of array.
|
||||
iter!(for pattern in array);
|
||||
}
|
||||
(_, Value::Dict(dict)) => {
|
||||
// Iterate over pairs of dict.
|
||||
iter!(for pattern in dict.pairs());
|
||||
}
|
||||
(_, Value::Array(array)) => {
|
||||
// Iterate over values of array.
|
||||
iter!(for pattern in array);
|
||||
(Pattern::Normal(_) | Pattern::Placeholder(_), Value::Str(str)) => {
|
||||
// Iterate over graphemes of string.
|
||||
iter!(for pattern in str.as_str().graphemes(true));
|
||||
}
|
||||
(ast::Pattern::Normal(_), _) => {
|
||||
(Pattern::Destructuring(_), Value::Str(_)) => {
|
||||
bail!(pattern.span(), "cannot destructure values of {}", iterable_type);
|
||||
}
|
||||
_ => {
|
||||
bail!(self.iterable().span(), "cannot loop over {}", iterable_type);
|
||||
}
|
||||
(_, _) => {
|
||||
bail!(pattern.span(), "cannot destructure values of {}", iterable_type)
|
||||
}
|
||||
}
|
||||
|
||||
if flow.is_some() {
|
||||
|
49
tests/typ/bugs/3275-loop-errors.typ
Normal file
49
tests/typ/bugs/3275-loop-errors.typ
Normal file
@ -0,0 +1,49 @@
|
||||
// Issue #3275: clearer errors for loops, https://github.com/typst/typst/issues/3275
|
||||
// Ref: false
|
||||
|
||||
---
|
||||
// Normal variable.
|
||||
#for x in (1, 2) {}
|
||||
#for x in (a: 1, b: 2) {}
|
||||
#for x in "foo" {}
|
||||
|
||||
---
|
||||
// Placeholder.
|
||||
#for _ in (1, 2) {}
|
||||
#for _ in (a: 1, b: 2) {}
|
||||
#for _ in "foo" {}
|
||||
|
||||
---
|
||||
// Destructuring.
|
||||
#for (k, v) in (("a", 1), ("b", 2), ("c", 3)) {}
|
||||
#for (k, ..) in (("a", 1), ("b", 2), ("c", 3)) {}
|
||||
#for (k, v) in (a: 1, b: 2, c: 3) {}
|
||||
#for (.., v) in (a: 1, b: 2, c: 3) {}
|
||||
|
||||
---
|
||||
// Error: 11-17 cannot loop over content
|
||||
#for x in [1, 2] {}
|
||||
|
||||
---
|
||||
// Error: 11-25 cannot loop over bytes
|
||||
#for _ in bytes((22, 0)) {}
|
||||
|
||||
---
|
||||
// Error: 16-21 cannot loop over integer
|
||||
#for (x, y) in 12306 {}
|
||||
|
||||
---
|
||||
// Error: 16-22 cannot loop over content
|
||||
#for (x, y) in [1, 2] {}
|
||||
|
||||
---
|
||||
// Error: 6-12 cannot destructure values of string
|
||||
#for (x, y) in "foo" {}
|
||||
|
||||
---
|
||||
// Error: 6-12 cannot destructure string
|
||||
#for (x, y) in ("foo", "bar") {}
|
||||
|
||||
---
|
||||
// Error: 6-12 cannot destructure integer
|
||||
#for (x, y) in (1, 2) {}
|
Loading…
x
Reference in New Issue
Block a user