···4455### Compiler
6677- - The compiler now issues a friendlier error when attempting to pattern match
88- on both the prefix and suffix of a string:
77+- The compiler now issues a friendlier error when attempting to pattern match
88+ on both the prefix and suffix of a string:
991010- ```
1111- error: Syntax error
1212- ┌─ /src/parse/error.gleam:2:23
1313- │
1414- 2 │ "prefix" <> infix <> "suffix" -> infix
1515- │ ^^^^^^^^^^^ This pattern is not allowed
1010+ ```
1111+ error: Syntax error
1212+ ┌─ /src/parse/error.gleam:2:23
1313+ │
1414+ 2 │ "prefix" <> infix <> "suffix" -> infix
1515+ │ ^^^^^^^^^^^ This pattern is not allowed
1616+1717+ A string pattern can only match on a literal string prefix.
16181717- A string pattern can only match on a literal string prefix.
1919+ Matching on a literal suffix is not possible, because `infix` would have an
2020+ unknown size.
2121+ ```
18221919- Matching on a literal suffix is not possible, because `infix` would have an
2020- unknown size.
2121- ```
2323+ ([Gavin Morrow](https://github.com/gavinmorrow))
22242323- ([Gavin Morrow](https://github.com/gavinmorrow))
2525+- Improved the error message shown when using an invalid discard name for
2626+ functions, constants, module names, and `as` patterns.
2727+ ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
24282529### Build tool
2630···3842 function, the return value of the extracted function is respected.
39434044 For example,
4545+4146 ```gleam
4247 fn wibble() {
4348 let wobble = fn() {
···4651 }
4752 }
4853 ```
5454+4955 is turned into
5656+5057 ```gleam
5158 fn wibble() {
5259 let wobble = fn() {
···6067 }
6168 ```
62696363- [Gavin Morrow](https://github.com/gavinmorrow)
7070+ ([Gavin Morrow](https://github.com/gavinmorrow))
···5858 pub location: SrcSpan,
5959}
60606161+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6262+/// Where we found an incorrect name.
6363+pub enum IncorrectNamePosition {
6464+ /// After `as`. For example: `as _wibble`.
6565+ AsPattern,
6666+ /// As a module in an import: `import _wibble`
6767+ Module,
6868+ /// As a function name: `fn _wibble()`
6969+ Function,
7070+ /// As an attribute name: `@_wibble`
7171+ Attribute,
7272+ /// As a constant name: `const _wibble = ...`
7373+ Constant,
7474+ /// As a target name: `@external(_wibble, ...)`
7575+ Target,
7676+ /// Used as a variable expression: `let a = _wibble`, `let a = _wibble(10)`
7777+ Variable,
7878+}
7979+6180#[derive(Debug, Clone, PartialEq, Eq)]
6281pub enum ParseErrorType {
6382 ExpectedEqual, // expect "="
···7392 ExpectedTargetName, // after "@target("
7493 ExprLparStart, // it seems "(" was used to start an expression
7594 ExtraSeparator, // #(1,,) <- the 2nd comma is an extra separator
7676- IncorrectName, // UpName or DiscardName used when Name was expected
7777- IncorrectUpName, // Name or DiscardName used when UpName was expected
7878- InvalidBitArraySegment, // <<7:hello>> `hello` is an invalid BitArray segment
7979- InvalidBitArrayUnit, // in <<1:unit(x)>> x must be 1 <= x <= 256
8080- InvalidTailPattern, // only name and _name are allowed after ".." in list pattern
8181- InvalidTupleAccess, // only positive int literals for tuple access
9595+ // UpName or DiscardName used when Name was expected
9696+ IncorrectName {
9797+ // Where we found the incorrect name.
9898+ kind: IncorrectNamePosition,
9999+ },
100100+ IncorrectUpName, // Name or DiscardName used when UpName was expected
101101+ InvalidBitArraySegment, // <<7:hello>> `hello` is an invalid BitArray segment
102102+ InvalidBitArrayUnit, // in <<1:unit(x)>> x must be 1 <= x <= 256
103103+ InvalidTailPattern, // only name and _name are allowed after ".." in list pattern
104104+ InvalidTupleAccess, // only positive int literals for tuple access
82105 LexError {
83106 error: LexicalError,
84107 },
···260283 extra_labels: vec![],
261284 },
262285263263- ParseErrorType::IncorrectName => ParseErrorDetails {
264264- text: "".into(),
265265- hint: Some(wrap(
266266- "Variable and module names start with a lowercase letter, \
267267-and can contain a-z, 0-9, or _.",
268268- )),
269269- label_text: "I'm expecting a lowercase name here".into(),
270270- extra_labels: vec![],
271271- },
286286+ ParseErrorType::IncorrectName { kind } => {
287287+ let subject = match kind {
288288+ IncorrectNamePosition::AsPattern => "A name after `as`",
289289+ IncorrectNamePosition::Module => "A module name",
290290+ IncorrectNamePosition::Function => "A function name",
291291+ IncorrectNamePosition::Attribute => "An attribute name",
292292+ IncorrectNamePosition::Constant => "A constant name",
293293+ IncorrectNamePosition::Target => "A target name",
294294+ IncorrectNamePosition::Variable => "A variable name",
295295+ };
296296+ ParseErrorDetails {
297297+ text: wrap_format!(
298298+ "{subject} must start with a lowercase letter, and can \
299299+contain a-z, 0-9, or _.",
300300+ ),
301301+ hint: None,
302302+ label_text: "I'm expecting a lowercase name here".into(),
303303+ extra_labels: vec![],
304304+ }
305305+ }
272306273307 ParseErrorType::IncorrectUpName => ParseErrorDetails {
274308 text: "".into(),
···15153 │ let val = _func_starting_with_underscore(1)
1616 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ I'm expecting a lowercase name here
17171818-Hint: Variable and module names start with a lowercase letter, and can
1919-contain
2020-a-z, 0-9, or _.
1818+A variable name must start with a lowercase letter, and can contain a-z,
1919+0-9, or _.
···17174 │ 1 -> _with_underscore(1)
1818 │ ^^^^^^^^^^^^^^^^ I'm expecting a lowercase name here
19192020-Hint: Variable and module names start with a lowercase letter, and can
2121-contain
2222-a-z, 0-9, or _.
2020+A variable name must start with a lowercase letter, and can contain a-z,
2121+0-9, or _.
···11+---
22+source: compiler-core/src/parse/tests.rs
33+expression: "pub fn main() {\n case todo {\n wibble as _wobble -> todo\n }\n}"
44+---
55+----- SOURCE CODE
66+pub fn main() {
77+ case todo {
88+ wibble as _wobble -> todo
99+ }
1010+}
1111+1212+----- ERROR
1313+error: Syntax error
1414+ ┌─ /src/parse/error.gleam:3:15
1515+ │
1616+3 │ wibble as _wobble -> todo
1717+ │ ^^^^^^^ I'm expecting a lowercase name here
1818+1919+A name after `as` must start with a lowercase letter, and can contain a-z,
2020+0-9, or _.