Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

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