Changelog#
Unreleased#
Build tool#
-
The
--templateflag forgleam newtakes the valueserlangandjavascriptto specify what target to use, witherlangbeing the default. (Mohammed Khouni) -
The Erlang/Elixir compiler process is now re-used for all packages, shaving off 0.3-0.5s per compiled package. (yoshi)
-
When a symlink cannot be made on Windows due to lack of permissions the error now includes information on how to enable Windows' developer mode, enabling symlinks. (Louis Pilfold)
-
The cli can now update individual dependencies.
gleam updateandgleam deps updatenow take an optional list of package names to update:gleam update package_a gleam deps update package_b package_cThis allows for selective updating of dependencies. When package names are provided, only those packages and their unique dependencies are unlocked and updated. If no package names are specified, the command behaves as before, updating all dependencies.
-
The
repositoryconfig ingleam.tomlcan now optionally include apathso that source links in generated documentation are correct for packages that aren't located at the root of their repository:repository = { type = "github", user = "gleam-lang", repo = "gleam", path = "packages/my_package" }
Compiler#
-
The compiler now prints correctly qualified or aliased type names when printing type errors.
This code:
pub type Int pub fn different_int_types(value: Int) { value } pub fn main() { different_int_types(20) }Produces this error:
error: Type mismatch ┌─ /src/wibble.gleam:8:23 │ 8 │ different_int_types(20) │ ^^ Expected type: Int Found type: gleam.Int -
The compiler can now suggest to pattern match on a
Result(a, b)if it's being used where a value of typeais expected. For example, this code:import gleam/list import gleam/int pub fn main() { let not_a_number = list.first([1, 2, 3]) int.add(1, not_a_number) }Results in the following error:
error: Type mismatch ┌─ /src/one/two.gleam:6:9 │ 6 │ int.add(1, not_a_number) │ ^^^^^^^^^^^^ Expected type: Int Found type: Result(Int, a) Hint: If you want to get a `Int` out of a `Result(Int, a)` you can pattern match on it: case result { Ok(value) -> todo Error(error) -> todo } -
Improved the error message for unknown record fields, displaying an additional note on how to have a field accessor only if it makes sense. (Giacomo Cavalieri)
-
The compiler now ignores
optionaldependencies when resolving versions unless explicitly specified. (Gustavo Inacio) -
Improved the error message for using
@deprecatedwith no deprecation message (Jiangda Wang) -
Optimised creation of bit arrays on the JavaScript target. (Richard Viney)
-
The compiler can now infer the variant of custom types within expressions that construct or pattern match on them.
Using this information it can now be more precise with exhaustiveness checking, identifying patterns for the other variants as unnecessary.
pub type Pet { Dog(name: String, cuteness: Int) Turtle(name: String, speed: Int, times_renamed: Int) } pub fn main() { // We know `charlie` is a `Dog`... let charlie = Doc("Charles", 1000) // ...so you do not need to match on the `Turtle` variant case charlie { Dog(..) -> todo } }This also means that the record update syntax can be used on multi-variant custom types, so long as the variant can be inferred from the surrounding code.
pub fn rename(pet: Pet, to name: String) -> Pet { case pet { Dog(..) -> Dog(..dog, name:) Turtle(..) -> Turtle(..pet, name:, times_renamed: pet.times_renamed + 1) } }Variant specific fields can also be used with the accessor syntax.
pub fn speed(pet: Pet) -> Int { case pet { Dog(..) -> 500 Turtle(..) -> pet.speed } } -
When targeting JavaScript the compiler now emits a warning for integer literals and constants that lie outside JavaScript's safe integer range:
warning: Int is outside the safe range on JavaScript ┌─ /Users/richard/Desktop/int_test/src/int_test.gleam:1:15 │ 1 │ pub const i = 9_007_199_254_740_992 │ ^^^^^^^^^^^^^^^^^^^^^ This is not a safe integer on JavaScript This integer value is too large to be represented accurately by JavaScript's number type. To avoid this warning integer values must be in the range -(2^53 - 1) - (2^53 - 1). See JavaScript's Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER properties for more information.
Formatter#
-
The formatter no longer removes the first argument from a function which is part of a pipeline if the first argument is a capture and it has a label. This snippet of code is left as is by the formatter:
pub fn divide(dividend a: Int, divisor b: Int) -> Int { a / b } pub fn main() { 10 |> divide(dividend: _, divisor: 2) }Whereas previously, the label of the capture variable would be lost:
pub fn divide(dividend a: Int, divisor b: Int) -> Int { a / b } pub fn main() { 10 |> divide(divisor: 2) }
Language Server#
-
The Language Server now displays correctly qualified or aliased type names when hovering over a value in a Gleam file:
import gleam/option const value = option.Some(1) // ^ hovering here shows `option.Option(Int)`import gleam/option.{type Option as Maybe} const value = option.Some(1) // ^ hovering here shows `Maybe(Int)` -
The Language Server now suggests a code action to add type annotations to local variables, constants and functions:
pub fn add_int_to_float(a, b) { a +. int.to_float(b) }Becomes:
pub fn add_int_to_float(a: Float, b: Int) -> Float { a +. int.to_float(b) } -
The Language Server now suggests a code action to convert qualified imports to unqualified imports, which updates all occurrences of the qualified name throughout the module:
import option pub fn main() { option.Some(1) }Becomes:
import option.{Some} pub fn main() { Some(1) } -
The Language Server now suggests a code action to convert unqualified imports to qualified imports, which updates all occurrences of the unqualified name throughout the module:
import list.{map} pub fn main() { map([1, 2, 3], fn(x) { x * 2 }) }Becomes:
import list.{} pub fn main() { list.map([1, 2, 3], fn(x) { x * 2 }) }
Bug Fixes#
-
Fixed a bug in the compiler where shadowing a sized value in a bit pattern would cause invalid erlang code to be generated. (Antonio Iaccarino)
-
Fixed a bug where the formatter would not format strings with big grapheme clusters properly. (Giacomo Cavalieri)
-
Fixed the
BitArrayconstructor not being present in the types for the JavaScript prelude. (Richard Viney) -
Fixed a bug where generated TypeScript definitions were invalid for opaque types that use a private type. (Richard Viney)
-
Fixed the prelude re-export in generated TypeScript definitions. (Richard Viney)
-
Fixed a bug where the compiler would incorrectly type-check and compile calls to functions with labelled arguments in certain cases. (Surya Rose)
-
Fixed a bug where importing type aliases that reference unimported modules would generate invalid TypeScript definitions. (Richard Viney)
-
When splitting a constant list made of records, the formatter will keep each item on its own line to make things easier to read. (Giacomo Cavalieri)
-
Fixed a bug where the compiler would crash when pattern matching on a type which was defined with duplicate fields in one of its variants. (Surya Rose)
-
Fixed a bug where the WASM compiler would return incomplete JavaScript when unsupported features were used. It now returns a compilation error. (Richard Viney)
-
Fixed a bug where incorrect code would be generated for external function on the Erlang target if any of their arguments were discarded. (Giacomo Cavalieri)
-
Fixed a bug in the error message when using wrong values in a pipe where the message would swap the "Expected" and "Found" types. (Markus Pettersson)
-
Fixed a bug where the parser would incorrectly parse a record constructor with no arguments. (Louis Pilfold)
-
Fixed a bug where the language server wouldn't show hints when hovering over the tail of a list. (Giacomo Cavalieri)
-
Fixed a bug where attempting to jump to the definition of a type from the annotation of a parameter of an anonymous function would do nothing. (Surya Rose)
v1.5.1 - 2024-09-26#
Bug Fixes#
- Fixed a bug where Erlang file paths would not be escaped on Windows. (Louis Pilfold)