Skip to content

Commit 1eb6000

Browse files
committed
Friendly error when using multiple spreads
1 parent d292718 commit 1eb6000

File tree

4 files changed

+74
-0
lines changed

4 files changed

+74
-0
lines changed

compiler-core/src/parse.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,15 @@ where
588588
elements_after_tail = Some(elements);
589589
}
590590
};
591+
592+
// See if there is another spread
593+
// like `[..wibble, wobble, ..wabble]`
594+
if let Some((start, end)) = self.maybe_one(&Token::DotDot) {
595+
return parse_error(
596+
ParseErrorType::ListSpreadWithAnotherSpread,
597+
SrcSpan { start, end },
598+
);
599+
}
591600
};
592601

593602
if tail.is_some() && !elements_end_with_comma {

compiler-core/src/parse/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ utf16_codepoint, utf32_codepoint, signed, unsigned, big, little, native, size, u
157157
"See: https://tour.gleam.run/basics/lists/".into(),
158158
],
159159
),
160+
ParseErrorType::ListSpreadWithAnotherSpread => (
161+
"I wasn't expecting a spread here",
162+
vec![
163+
"Hint: use list.append(list1, list2) to join two lists.".into(),
164+
"See: https://hexdocs.pm/gleam_stdlib/gleam/list.html#append".into(),
165+
],
166+
),
160167
ParseErrorType::ListSpreadFollowedByElements => (
161168
"I wasn't expecting elements after this",
162169
vec![
@@ -375,6 +382,7 @@ pub enum ParseErrorType {
375382
UnknownTarget, // an unknown target was used
376383
ListSpreadWithoutElements, // Pointless spread: `[..xs]`
377384
ListSpreadFollowedByElements, // trying to append something after the spread: `[..xs, x]`
385+
ListSpreadWithAnotherSpread, // trying to use multiple spreads: `[..xs, ..ys]`
378386
LowcaseBooleanPattern, // most likely user meant True or False in patterns
379387
UnexpectedLabel, // argument labels were provided, but are not supported in this context
380388
UnexpectedEof,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
source: compiler-core/src/parse/tests.rs
3+
expression: "\npub fn main() -> Nil {\n let xs = [1, 2, 3]\n let ys = [5, 6, 7]\n [..xs, 4, ..ys]\n}\n"
4+
---
5+
----- SOURCE CODE
6+
7+
pub fn main() -> Nil {
8+
let xs = [1, 2, 3]
9+
let ys = [5, 6, 7]
10+
[..xs, 4, ..ys]
11+
}
12+
13+
14+
----- ERROR
15+
error: Syntax error
16+
┌─ /src/parse/error.gleam:5:13
17+
18+
5 │ [..xs, 4, ..ys]
19+
^^ I wasn't expecting a spread here
20+
21+
Hint: use list.append(list1, list2) to join two lists.
22+
See: https://hexdocs.pm/gleam_stdlib/gleam/list.html#append

compiler-core/src/parse/tests.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,28 @@ fn pointless_spread() {
363363
);
364364
}
365365

366+
#[test]
367+
fn double_spread() {
368+
assert_error!(
369+
"let xs = [1] let ys = [2, 3] [..xs, ..ys]",
370+
ParseError {
371+
error: ParseErrorType::ListSpreadWithAnotherSpread,
372+
location: SrcSpan { start: 36, end: 38 },
373+
}
374+
);
375+
}
376+
377+
#[test]
378+
fn double_spread2() {
379+
assert_error!(
380+
"let xs = [1] let ys = [3, 4] [..xs, 2, ..ys]",
381+
ParseError {
382+
error: ParseErrorType::ListSpreadWithAnotherSpread,
383+
location: SrcSpan { start: 39, end: 41 },
384+
}
385+
);
386+
}
387+
366388
// https://github.com/gleam-lang/gleam/issues/1358
367389
#[test]
368390
fn lowcase_bool_in_pattern() {
@@ -788,6 +810,19 @@ pub fn main() -> Nil {
788810
);
789811
}
790812

813+
#[test]
814+
fn list_spread_followed_by_another_spread() {
815+
assert_module_error!(
816+
r#"
817+
pub fn main() -> Nil {
818+
let xs = [1, 2, 3]
819+
let ys = [5, 6, 7]
820+
[..xs, 4, ..ys]
821+
}
822+
"#
823+
);
824+
}
825+
791826
#[test]
792827
fn list_spread_as_first_item_followed_by_other_items() {
793828
assert_module_error!(

0 commit comments

Comments
 (0)