Fork of daniellemaywood.uk/gleam — Wasm codegen work
1<!--
2 SPDX-License-Identifier: Apache-2.0
3 SPDX-FileCopyrightText: 2020 The Gleam contributors
4-->
5
6# Changelog
7
8## v1.13.0 - 2025-10-19
9
10## v1.13.0-rc2 - 2025-10-06
11
12### Bug fixes
13
14- Fixed a bug where the "Extract function" code action would not properly
15 extract a `use` expression.
16 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
17
18- Fixed a bug where the "Extract function" code action would generate a function
19 with the wrong type when used on a use expression.
20 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
21
22- Fixed a bug where the error message for inexhaustive patterns could show
23 incorrect extra patterns in addition to the correct missing patterns.
24 ([Adi Salimgereyev](https://github.com/abs0luty))
25
26- Fixed a bug where triggering the "Generate function" code action to generate
27 a function in a different module could cause the generated function to appear
28 in the middle of an existing function, resulting in invalid code.
29 ([Surya Rose](https://github.com/GearsDatapacks))
30
31- Fixed a bug where the "turn into pipe" code action would not trigger inside
32 the final step of a pipeline.
33 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
34
35- Fixed a bug where the "pattern match on variable" code action would crash when
36 used on a variable followed by a case expression.
37 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
38
39## v1.13.0-rc1 - 2025-09-29
40
41### Compiler
42
43- The compiler now applies an optimisation known as "interference based pruning"
44 when compiling bit array pattern matching where matches are performed at the
45 start of bit arrays.
46 This optimisation drastically reduces compile times, memory usage and the
47 compiled code size, removing many redundant checks.
48 It is particularly important for network protocol applications where it is
49 typical to match on some fixed patterns at the start of the bitarray.
50 For example:
51
52 ```gleam
53 pub fn parser_headers(headers: BitArray, bytes: Int) -> Headers {
54 case headers {
55 <<"CONTENT_LENGTH" as header, 0, value:size(bytes), 0, rest:bytes>>
56 | <<"QUERY_STRING" as header, 0, value:size(bytes), 0, rest:bytes>>
57 | <<"REQUEST_URI" as header, 0, value:size(bytes), 0, rest:bytes>>
58 // ...
59 | <<"REDIRECT_STATUS" as header, 0, value:size(bytes), 0, rest:bytes>>
60 | <<"SCRIPT_NAME" as header, 0, value:size(bytes), 0, rest:bytes>>
61 -> [#(header, value), ..parse_headers(rest)]
62 }
63 }
64 ```
65
66 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
67
68- The compiler now raises a warning for unreachable clauses that are matching
69 on bit array segments that could never match. Consider this example:
70
71 ```gleam
72 pub fn get_payload(packet: BitArray) -> Result(BitArray, Nil) {
73 case packet {
74 <<200, payload:bytes>> -> Ok(payload)
75 <<404, _:bits>> -> Error(Nil)
76 _ -> Ok(packet)
77 }
78 }
79 ```
80
81 There's a subtle bug here. The second clause can never match since it's
82 impossible for the first byte of the bit array to have the value `404`.
83 The new error explains this nicely:
84
85 ```txt
86 warning: Unreachable pattern
87 ┌─ /src.gleam:4:5
88 │
89 4 │ <<404, _:bits>> -> Error(Nil)
90 │ ^^^^^^^^^^^^^^^
91 │ │
92 │ A 1 byte unsigned integer will never match this value
93
94 This pattern cannot be reached as it contains segments that will never
95 match.
96
97 Hint: It can be safely removed.
98 ```
99
100 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
101
102- The compiler now raises a warning when a function's argument is only passed
103 along in a recursive call but not actually used for anything. For example:
104
105 ```gleam
106 import gleam/io
107
108 pub fn greet(x, times) {
109 case times {
110 0 -> Nil
111 _ -> {
112 io.println("Hello, Joe!")
113 greet(x, times - 1)
114 }
115 }
116 }
117 ```
118
119 In this piece of code the `x` argument is actually never used, and the
120 compiler will raise the following warning:
121
122 ```txt
123 warning: Unused function argument
124 ┌─ /Users/giacomocavalieri/Desktop/prova/src/prova.gleam:3:14
125 │
126 3 │ pub fn greet(x, times) {
127 │ ^ This argument is unused
128
129 This argument is passed to the function when recursing, but it's never used
130 for anything.
131 ```
132
133 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
134
135- The compiler now emits a better error message for private types marked as
136 opaque. For example, the following piece of code:
137
138 ```gleam
139 opaque type Wibble {
140 Wobble
141 }
142 ```
143
144 Would result in the following error:
145
146 ```
147 error: Private opaque type
148 ┌─ /src/one/two.gleam:2:1
149 │
150 2 │ opaque type Wibble {
151 │ ^^^^^^ You can safely remove this.
152
153 Only a public type can be opaque.
154 ```
155
156 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
157
158- The parsing of opaque private types is now fault tolerant: having a private
159 opaque type in a module no longer stops the compiler from highlighting other
160 errors.
161 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
162
163- The compiler now emits a single warning for multiple negations in a row, while
164 previously it would emit multiple comments highlighting increasingly longer
165 spans.
166 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
167
168- Redundant `_ as x` patterns are now deprecated in favour of `x`.
169 ([eutampieri](https://github.com/eutampieri))
170
171- The compiler will now raise warning for inefficient use of `list.length()`
172 when trying to check is list empty via `0 < list.length(list)` or
173 `list.length(list) > 0` as well as in other cases. For example, the following
174 code:
175
176 ```gleam
177 import gleam/list
178
179 pub fn main() {
180 let numbers = [1, 46]
181 let _ = 0 < list.length(numbers)
182 let _ = list.length(numbers) > 0
183 }
184 ```
185
186 Would result in following warnings:
187
188 ```
189 warning: Inefficient use of `list.length`
190 ┌─ /data/data/com.termux/files/home/test_gleam/src/test_gleam.gleam:5:13
191 │
192 5 │ let _ = 0 < list.length(numbers)
193 │ ^^^^^^^^^^^^^^^^^^^^^^^^
194
195 The `list.length` function has to iterate across the whole
196 list to calculate the length, which is wasteful if you only
197 need to know if the list is empty or not.
198
199 Hint: You can use `the_list != []` instead.
200
201 warning: Inefficient use of `list.length`
202 ┌─ /data/data/com.termux/files/home/test_gleam/src/test_gleam.gleam:6:13
203 │
204 6 │ let _ = list.length(numbers) > 0
205 │ ^^^^^^^^^^^^^^^^^^^^^^^^
206
207 The `list.length` function has to iterate across the whole
208 list to calculate the length, which is wasteful if you only
209 need to know if the list is empty or not.
210
211 Hint: You can use `the_list != []` instead.
212 ```
213
214 ([Andrey Kozhev](https://github.com/ankddev))
215
216- The compiler now provides an improved error message for when trying to define
217 a constant inside a function. For example, the following code:
218
219 ```gleam
220 pub fn deep_thought() -> Int {
221 const the_answer = 42
222 the_answer
223 }
224 ```
225
226 Will produce this error message:
227
228 ```txt
229 error: Syntax error
230 ┌─ /src/file.gleam:2:3
231 │
232 3 │ const the_answer = 43
233 │ ^^^^^ Constants are not allowed inside functions
234
235 All variables are immutable in Gleam, so constants inside functions are not
236 necessary.
237 Hint: Either move this into the global scope or use `let` binding instead.
238 ```
239
240 ([Surya Rose](https://github.com/GearsDatapacks))
241
242- The code generated for blocks on the JavaScript target has been improved and
243 is now smaller in certain cases.
244 ([Surya Rose](https://github.com/GearsDatapacks))
245
246- Writing a type name followed by `()` now emits an error during analysis
247 rather than parsing, so it no longer stops the compiler from reporting errors
248 further in the code.
249 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
250
251- The compiler now shows a specific syntax error when trying to use an
252 angle-bracket syntax for generic types or function definitions:
253
254 ```txt
255 error: Syntax error
256 ┌─ /src/parse/error.gleam:2:12
257 │
258 2 │ type Either<a, b> {
259 │ ^ I was expecting `(` here.
260
261 Type parameters use lowercase names and are surrounded by parentheses.
262
263 type Either(a, b) {
264
265 See: https://tour.gleam.run/data-types/generic-custom-types/
266 ```
267
268 ([Aaron Christiansen](https://github.com/AaronC81))
269
270- Fault tolerance for analysis of labeled fields in variant patterns has
271 been improved.
272 ([sobolevn](https://github.com/sobolevn))
273
274- Compiler now adds a hint when `#`-styled comments are used. This code:
275
276 ```gleam
277 fn some() {
278 let a = 1
279 # let b = 2
280 }
281 ```
282
283 Now produces:
284
285 ```txt
286 error: Syntax error
287 ┌─ /src/main.gleam:3:5
288 │
289 3 │ # let b = 2
290 │ ^^^ I was not expecting this
291
292 Found the keyword `let`, expected one of:
293 - `(`
294 Hint: Maybe you meant to create a comment?
295 Comments in Gleam start with `//`, not `#`
296 ```
297
298 ([sobolevn](https://github.com/sobolevn))
299
300- The `erlang.application_start_argument` parameter has been added to
301 `gleam.toml`. This is a string containing an Erlang term that will be written
302 into the package's Erlang `.app` file if `erlang.application_start_module`
303 has been set, replacing the default argument of `[]`.
304 ([Louis Pilfold](https://github.com/lpil))
305
306- Generated code for the JavaScript target now includes a public API which can
307 be used for FFI interacting with Gleam custom types. For example, if you have
308 this Gleam code:
309
310 ```gleam
311 pub type Person {
312 Teacher(name: String, subject: String)
313 Student(name: String, age: Int)
314 }
315 ```
316
317 You can use the new API to use the `Person` type in FFI code:
318
319 ```javascript
320 import {...} from "./person.mjs";
321
322 // Constructing custom types
323 let teacher = Person$Teacher("Joe Armstrong", "Computer Science");
324 let student = Person$Student("Louis Pilfold");
325
326 let randomPerson = Math.random() > 0.5 ? teacher : student;
327
328 // Checking variants
329 let randomIsTeacher = Person$isTeacher(randomPerson);
330
331 // Getting fields
332 let teacherSubject = Person$Teacher$subject(teacher);
333
334 // The `name` field is shared so can be accessed from either variant
335 let personName = Person$name(randomPerson);
336 ```
337
338 ([Surya Rose](https://github.com/GearsDatapacks))
339
340### Build tool
341
342- New projects are generated using OTP28 on GitHub Actions.
343 ([Louis Pilfold](https://github.com/lpil))
344
345- The build tool now has a new `hex owner transfer` subcommand to transfer
346 ownership of existing packages.
347 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
348
349- `gleam add` now adds `dependencies` and `dev_dependencies` as tables instead
350 of inline tables if they are missing.
351 ([Andrey Kozhev](https://github.com/ankddev))
352
353- After dependency resolution the build tool will now print all packages added
354 and removed, and any versions changed.
355 ([Louis Pilfold](https://github.com/lpil))
356
357- `gleam publish` now blocks publishing packages that contain the default main
358 function to prevent accidental publishing of unmodified template code.
359 ([Joohoon Cha](https://github.com/jcha0713))
360
361- When generating documentation, the build tool will now print the names of
362 public type aliases instead of internal type names when annotating functions
363 and types. For example, for the following code:
364
365 ```gleam
366 import my_package/internal
367
368 pub type ExternalAlias = internal.InternalRepresentation
369
370 pub fn do_thing() -> ExternalAlias { ... }
371 ```
372
373 This is what the build tool used to generate:
374
375 ```gleam
376 pub fn do_thing() -> @internal InternalRepresentation
377 ```
378
379 Whereas now it will not use the internal name, and instead produce:
380
381 ```gleam
382 pub fn do_thing() -> ExternalAlias
383 ```
384
385 ([Surya Rose](https://github.com/GearsDatapacks))
386
387- Support has been added for using Tangled as a repository.
388 ([Naomi Roberts](https://github.com/naomieow))
389
390### Language server
391
392- The language server now offers a code action to remove all the unreachable
393 clauses in a case expression. For example:
394
395 ```gleam
396 pub fn main() {
397 case find_user() {
398 Ok(user) -> todo
399 Ok(Admin) -> todo
400 // ^^^^^^^^^ This clause is unreachable
401 Ok(User) -> todo
402 // ^^^^^^^^ This clause is unreachable
403 Error(_) -> todo
404 }
405 }
406 ```
407
408 Hovering over one of the unreachable clauses and triggering the code action
409 would remove all the unreachable clauses:
410
411 ```gleam
412 pub fn main() {
413 case find_user() {
414 Ok(user) -> todo
415
416 Error(_) -> todo
417 }
418 }
419 ```
420
421 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
422
423- The "pattern match on variable" can now be triggered on lists. For example:
424
425 ```gleam
426 pub fn is_empty(list: List(a)) -> Bool {
427 // ^^^^ Triggering the action here
428 }
429 ```
430
431 Triggering the action on the `list` argument would result in the following
432 code:
433
434 ```gleam
435 pub fn is_empty(list: List(a)) -> Bool {
436 case list {
437 [] -> todo
438 [first, ..rest] -> todo
439 }
440 }
441 ```
442
443 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
444
445- The "pattern match on variable" code action can now be triggered on variables
446 introduced by other patterns. For example:
447
448 ```gleam
449 pub fn main() {
450 let User(name:, role:) = find_user("lucy")
451 // ^^^^ Triggering the action here
452 }
453 ```
454
455 Triggering the action on another variable like `role` would result in the
456 following code:
457
458 ```gleam
459 pub fn main() {
460 let User(name:, role:) = find_user("lucy")
461 case role {
462 Admin -> todo
463 Member -> todo
464 }
465 }
466 ```
467
468 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
469
470- The "pattern match on variable" code action can now be triggered on variables
471 in case expressions. For example:
472
473 ```gleam
474 pub fn main() {
475 case find_user() {
476 Ok(user) -> todo
477 Error(_) -> todo
478 }
479 }
480 ```
481
482 Triggering the action on the `user` variable would result in the following
483 code:
484
485 ```gleam
486 pub fn main() {
487 case find_user() {
488 Ok(Admin) -> todo
489 Ok(Member) -> todo
490 Error(_) -> todo
491 }
492 }
493 ```
494
495 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
496
497- The language server now offers a quick fix to remove `opaque` from a private
498 type:
499
500 ```gleam
501 opaque type Wibble {
502 // ^^^ This is an error!
503 Wobble
504 }
505 ```
506
507 If you hover over the type and trigger the quick fix, the language server will
508 automatically remove the `opaque` keyword:
509
510 ```gleam
511 type Wibble {
512 Wobble
513 }
514 ```
515
516 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
517
518- The language server now offers a code action to add the omitted labels in a
519 call. For example:
520
521 ```gleam
522 pub type User {
523 User(first_name: String, last_name: String, likes: List(String))
524 }
525
526 pub fn main() {
527 let first_name = "Giacomo"
528 User(first_name, "Cavalieri", ["gleam"])
529 //^^^^ Triggering the code action here
530 }
531 ```
532
533 Triggering the code action on the `User` constructor will result in the
534 following code:
535
536 ```gleam
537 pub type User {
538 User(first_name: String, last_name: String, likes: List(String))
539 }
540
541 pub fn main() {
542 let first_name = "Giacomo"
543 User(first_name:, last_name: "Cavalieri", likes: ["gleam"])
544 }
545 ```
546
547- The "inline variable" code action is now only suggested when hovering over the
548 relevant variable.
549 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
550
551- When hovering over a record field in a record access expression, the language
552 sever will now show the documentation for that field, if present.
553 ([Surya Rose](https://github.com/GearsDatapacks))
554
555- Renaming a variable from a label shorthand (`name:`) no longer includes the
556 colon in the rename dialog (`name:` -> `name`)
557 ([fruno](https://github.com/frunobulax-the-poodle))
558
559- The language server now offers a code action to collapse nested case
560 expressions. Take this example:
561
562 ```gleam
563 case user {
564 User(role: Admin, name:) ->
565 // Here the only thing we're doing is pattern matching on the
566 // `name` variable we've just defined in the outer pattern.
567 case name {
568 "Joe" -> "Hello, Joe!"
569 _ -> "Hello, stranger"
570 }
571
572 _ -> "You're not an admin!"
573 }
574 ```
575
576 We could simplify this case expression and reduce nesting like so:
577
578 ```gleam
579 case user {
580 User(role: Admin, name: "Joe") -> "Hello, Joe!"
581 User(role: Admin, name: _) -> "Hello, stranger"
582 _ -> "You're not an admin!"
583 }
584 ```
585
586 Now, if you hover over that pattern, the language server will offer the
587 "collapse nested case" action that will simplify your code like shown in the
588 example above.
589
590 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
591
592- The "Generate function" code action now allows generating function in other
593 modules. For example, given the following code:
594
595 ```gleam
596 // maths.gleam
597 pub fn add(a: Int, b: Int) -> Int { a + b }
598
599 // main.gleam
600 import maths
601
602 pub fn main() -> Int {
603 echo maths.add(1, 2)
604 echo maths.subtract(from: 2, subtract: 1)
605 // ^ Trigger the "Generate function" code action here
606 }
607 ```
608
609 The language sever will edit the `maths.gleam` file:
610
611 ```gleam
612 pub fn add(a: Int, b: Int) -> Int { a + b }
613
614 pub fn subtract(from from: Int, subtract subtract: Int) -> Int {
615 todo
616 }
617 ```
618
619 ([Surya Rose](https://github.com/GearsDatapacks))
620
621- The "Add type annotations" and "Generate function" code actions now ignore
622 type variables defined in other functions, improving the generated code.
623 For example:
624
625 ```gleam
626 fn something(a: a, b: b, c: c) -> d { todo }
627
628 fn pair(a, b) { #(a, b) }
629 ```
630
631 Previously, when triggering the "Add type annotations" code action on the
632 `pair` function, the language server would have generated:
633
634 ```gleam
635 fn pair(a: e, b: f) -> #(e, f) { #(a, b) }
636 ```
637
638 However in 1.13, it will now generate:
639
640 ```gleam
641 fn pair(a: a, b: b) -> #(a, b) { #(a, b) }
642 ```
643
644 ([Surya Rose](https://github.com/GearsDatapacks))
645
646- You can now go to definition, rename, etc. from alternative patterns!
647
648 ```gleam
649 case wibble {
650 Wibble | Wobble -> 0
651 // ^- Previously you could not trigger actions from here
652 }
653
654 ```
655
656 ([fruno](https://github.com/fruno-bulax))
657
658- When showing types of values on hover, or adding type annotations, the language
659 server will now prefer public type aliases to internal types. For example, if
660 the "Add type annotations" code action was triggered on the following code:
661
662 ```gleam
663 import lustre/html
664 import lustre/element
665 import lustre/attribute
666
667 pub fn make_link(attribute, element) {
668 html.a([attribute], [elements])
669 }
670 ```
671
672 Previously, the following code would have been generated:
673
674 ```gleam
675 pub fn make_link(
676 attribute: vattr.Attribute,
677 element: vdom.Element(a)
678 ) -> vdom.Element(a) {
679 html.a([attribute], [elements])
680 }
681 ```
682
683 Which references internal types which should not be imported by the user.
684 However, now the language server will produce the following:
685
686 ```gleam
687 pub fn make_link(
688 attribute: attribute.Attribute,
689 element: element.Element(a)
690 ) -> element.Element(a) {
691 html.a([attribute], [elements])
692 }
693 ```
694
695 ([Surya Rose](https://github.com/GearsDatapacks))
696
697- The language server now offers the `convert to case` code action only if a
698 single `let assert` expression is selected.
699 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
700
701- The language server now offers an "Extract function" code action to extract a
702 selected piece of code into a separate function. For example:
703
704 ```gleam
705 const head_byte_count = 256
706
707 pub fn get_head_of_file() {
708 let assert Ok(contents) = read_file()
709
710 case contents {
711 //^ Select from here
712 <<head:bytes-size(head_byte_count), _:bits>> -> Ok(head)
713 _ -> Error(Nil)
714 }
715 //^ Until here
716 }
717 ```
718
719 Would become:
720
721 ```gleam
722 const head_byte_count = 256
723
724 pub fn get_head_of_file() {
725 let assert Ok(contents) = read_file()
726
727 function(contents)
728 }
729
730 fn function(contents: BitArray) -> Result(BitArray, Nil) {
731 case contents {
732 <<head:bytes-size(head_byte_count), _:bits>> -> Ok(head)
733 _ -> Error(Nil)
734 }
735 }
736 ```
737
738 You can then use language server renaming to choose an appropriate name for
739 the new function.
740
741 ([Surya Rose](https://github.com/GearsDatapacks))
742
743### Formatter
744
745- The formatter now removes needless multiple negations that are safe to remove.
746 For example, this snippet of code:
747
748 ```gleam
749 pub fn useless_negations() {
750 let lucky_number = --11
751 let lucy_is_a_star = !!!False
752 }
753 ```
754
755 Is rewritten as:
756
757 ```gleam
758 pub fn useless_negations() {
759 let lucky_number = 11
760 let lucy_is_a_star = !False
761 }
762 ```
763
764 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
765
766- Redundant `_ as x` patterns are rewritten to `x`.
767 ([eutampieri](https://github.com/eutampieri))
768
769- The formatter no longer removes blocks from case clause guards.
770 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
771
772- The formatter now properly formats tuple return annotation with comments.
773 ([Andrey Kozhev](https://github.com/ankddev))
774
775### Bug fixes
776
777- Fixed a bug where literals using `\u{XXXX}` syntax in bit array pattern
778 segments were not translated to Erlang's `\x{XXXX}` syntax correctly.
779 ([Benjamin Peinhardt](https://github.com/bcpeinhardt))
780
781- Fixed a bug where `echo` could crash on JavaScript if the module contains
782 record variants with the same name as some built-in JavaScript objects.
783 ([Louis Pilfold](https://github.com/lpil))
784
785- Fixed a bug where the compiler would highlight an entire double negation
786 expression as safe to remove, instead of just highlighting the double
787 negation.
788 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
789
790- Fixed a bug where the compiler would crash if there was an invalid version
791 requirement in a project's `gleam.toml`.
792 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
793
794- Fixed a bug where the compiler would suggest a discouraged project name as an
795 alternative to the reserved `gleam` name.
796 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
797
798- Fixed a bug where Forgejo source URLs in the HTML documentation could be
799 incorrectly structured.
800 ([Louis Pilfold](https://github.com/lpil))
801
802- The compiler now emits an error when a module in the `src` directory imports
803 a dev dependency, while previously it would incorrectly let these
804 dependencies to be imported.
805 ([Surya Rose](https://github.com/GearsDatapacks))
806
807- Erroneous extra fields in `gleam.toml` dependency specifications will no
808 longer be siltently ignored. An error is now returned highlighting the
809 problem instead.
810 ([Louis Pilfold](https://github.com/lpil))
811
812- Fixed a bug where renaming a constant which is referenced in another module
813 inside a guard would generate invalid code.
814 ([Surya Rose](https://github.com/GearsDatapacks))
815
816- Fixed a bug where `echo .. as ..` message will be omitted in browser target.
817 ([Andrey Kozhev](https://github.com/ankddev))
818
819- Fixed a bug where renaming a variable used in a record update would produce
820 invalid code in certain situations.
821 ([Surya Rose](https://github.com/GearsDatapacks))
822
823- Fixed a bug where adding `echo` to the subject of a `case` expression would
824 prevent variant inference from working correctly.
825 ([Surya Rose](https://github.com/GearsDatapacks))
826
827- Fixed a bug where the compiler would suggest to use a discarded value defined
828 in a different function.
829 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
830
831- Fixed a bug where the formatter would format a panic message adding more
832 nesting than necessary.
833 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
834
835- Fixed a bug where the language server wouldn't offer the "unqualify" code
836 action if used on a type alias.
837 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
838
839- Fixed a bug where the language server would fail to rename an external
840 function with no body.
841 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
842
843- Fixed a bug where the compiler allowed to write a guard with an empty clause.
844 ([Tristan-Mihai Radulescu](https://github.com/Courtcircuits))
845
846- Fixed a bug where switching from a hex dependency to a git dependency would
847 result in an error from the compiler.
848 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
849
850- Fixed a bug where the compiler would reference a redeclared variable in a let
851 assert message, instead of the original variable, on the Erlang target.
852 ([Danielle Maywood](https://github.com/DanielleMaywood))
853
854- Fixed a bug where the compiler would report an imported module as unused if it
855 were used by private functions only.
856 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
857
858- Fixed a bug where the "Extract variable" code action would shadow existing
859 variables, constants and function names.
860 ([Matias Carlander](https://github.com/matiascr))
861
862- Fixed a bug where the language server would not fill in the missing labels of
863 a pattern correctly, generating invalid code.
864 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
865
866- Fixed a bug where invalid code was being generated when using the "Extract
867 variable" code action inside an anonymous function.
868 ([Matias Carlander](https://github.com/matiascr))
869
870- Fixed a bug where running `gleam update` would not properly update git
871 dependencies unless `gleam clean` was run first.
872 ([Surya Rose](https://github.com/GearsDatapacks))
873
874- Fixed a bug where the compiler would produce wrong JavaScript code for binary
875 pattern matching expressions using literal strings and byte segments.
876 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
877
878- Fixed a bug where the build tool would crash when trying to add transitive dependency.
879 ([Andrey Kozhev](https://github.com/ankddev))