From 34550220aee087271769fb9e5d94d1faebe243c1 Mon Sep 17 00:00:00 2001 From: Malo <57839069+MDLC01@users.noreply.github.com> Date: Sun, 16 Jun 2024 11:35:18 +0200 Subject: [PATCH] Add hints to array destructuring error messages (#4400) --- crates/typst/src/eval/binding.rs | 27 ++++++++++++++++++++++--- tests/suite/scripting/destructuring.typ | 13 ++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/crates/typst/src/eval/binding.rs b/crates/typst/src/eval/binding.rs index 8a2d91eef..4201faed4 100644 --- a/crates/typst/src/eval/binding.rs +++ b/crates/typst/src/eval/binding.rs @@ -96,7 +96,10 @@ where match p { ast::DestructuringItem::Pattern(pattern) => { let Ok(v) = value.at(i as i64, None) else { - bail!(pattern.span(), "not enough elements to destructure"); + bail!( + pattern.span(), "not enough elements to destructure"; + hint: "the provided array has a length of {len}", + ); }; destructure_impl(vm, pattern, v, f)?; i += 1; @@ -105,7 +108,10 @@ where let sink_size = (1 + len).checked_sub(destruct.items().count()); let sink = sink_size.and_then(|s| value.as_slice().get(i..i + s)); let (Some(sink_size), Some(sink)) = (sink_size, sink) else { - bail!(spread.span(), "not enough elements to destructure"); + bail!( + spread.span(), "not enough elements to destructure"; + hint: "the provided array has a length of {len}", + ); }; if let Some(expr) = spread.sink_expr() { f(vm, expr, Value::Array(sink.into()))?; @@ -119,7 +125,22 @@ where } if i < len { - bail!(destruct.span(), "too many elements to destructure"); + if i == 0 { + bail!( + destruct.span(), "too many elements to destructure"; + hint: "the provided array has a length of {len}, but the pattern expects an empty array", + ) + } else if i == 1 { + bail!( + destruct.span(), "too many elements to destructure"; + hint: "the provided array has a length of {len}, but the pattern expects a single element", + ); + } else { + bail!( + destruct.span(), "too many elements to destructure"; + hint: "the provided array has a length of {len}, but the pattern expects {i} elements", + ); + } } Ok(()) diff --git a/tests/suite/scripting/destructuring.typ b/tests/suite/scripting/destructuring.typ index 0a3c1c548..9d28c195f 100644 --- a/tests/suite/scripting/destructuring.typ +++ b/tests/suite/scripting/destructuring.typ @@ -119,12 +119,22 @@ // Error: 7-14 expected pattern, found function call #let (a.at(0),) = (1,) +--- destructuring-let-empty-array --- +#let () = () + +--- destructuring-let-empty-array-too-many-elements --- +// Error: 6-8 too many elements to destructure +// Hint: 6-8 the provided array has a length of 2, but the pattern expects an empty array +#let () = (1, 2) + --- destructuring-let-array-too-few-elements --- // Error: 13-14 not enough elements to destructure +// Hint: 13-14 the provided array has a length of 2 #let (a, b, c) = (1, 2) --- destructuring-let-array-too-few-elements-with-sink --- // Error: 7-10 not enough elements to destructure +// Hint: 7-10 the provided array has a length of 2 #let (..a, b, c, d) = (1, 2) --- destructuring-let-array-bool-invalid --- @@ -183,6 +193,7 @@ --- destructuring-let-array-trailing-placeholders --- // Trailing placeholders. // Error: 10-11 not enough elements to destructure +// Hint: 10-11 the provided array has a length of 1 #let (a, _, _, _, _) = (1,) #test(a, 1) @@ -350,8 +361,10 @@ --- issue-3275-destructuring-loop-over-2d-array-1 --- // Error: 10-11 not enough elements to destructure +// Hint: 10-11 the provided array has a length of 1 #for (x, y) in ((1,), (2,)) {} --- issue-3275-destructuring-loop-over-2d-array-2 --- // Error: 6-12 too many elements to destructure +// Hint: 6-12 the provided array has a length of 3, but the pattern expects 2 elements #for (x, y) in ((1,2,3), (4,5,6)) {}