Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,60 @@
# Changelog

## Unreleased

### Build tool

- Now build tool ignores type variables defined in other functions and types,
improving hints in errors. For example:

```gleam
pub type Wibble(a, b, c, d, e, f, g) {
Wibble(value: a)
}

pub fn main() {
let x: Nil = []
}
```

Previously this code would have emit following error:

```text
error: Type mismatch
┌─ C:\Users\user\projects\test_gleam\src\test_gleam.gleam:6:16
6 │ let x: Nil = []
│ ^^

Expected type:

Nil

Found type:

List(h)
```

Now it will emit following error:

```text
error: Type mismatch
┌─ C:\Users\user\projects\test_gleam\src\test_gleam.gleam:6:16
6 │ let x: Nil = []
│ ^^

Expected type:

Nil

Found type:

List(a)
```

([Andrey Kozhev](https://github.com/ankddev))

## v1.13.0-rc2 - 2025-10-06

### Bug fixes
Expand Down
20 changes: 10 additions & 10 deletions compiler-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1929,7 +1929,7 @@ value has. It seems to be defined in terms of itself.",
}

TypeError::NotFn { location, type_ } => {
let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);
let text = format!(
"This value is being called as a function but its type is:\n\n {}",
printer.print_type(type_)
Expand Down Expand Up @@ -1959,7 +1959,7 @@ value has. It seems to be defined in terms of itself.",
fields,
unknown_field: variants,
} => {
let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);

// Give a hint about what type this value has.
let mut text = format!(
Expand Down Expand Up @@ -2051,7 +2051,7 @@ to call a method on this value you may want to use the function syntax instead."
given,
situation: Some(UnifyErrorSituation::Operator(op)),
} => {
let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);
let mut text = format!(
"The {op} operator expects arguments of this type:

Expand Down Expand Up @@ -2103,7 +2103,7 @@ But this argument has this type:
.and_then(|(arguments, _)| arguments.first().cloned())
.unwrap_or_else(|| given.clone());

let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);
let text = format!(
"The argument is:

Expand Down Expand Up @@ -2143,7 +2143,7 @@ But function expects:
given,
situation,
} => {
let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);
let mut text = if let Some(description) =
situation.as_ref().and_then(|s| s.description())
{
Expand Down Expand Up @@ -2386,7 +2386,7 @@ specify all fields explicitly instead of using the record update syntax."
field_name,
..
} => {
let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);
let expected_field_type = printer.print_type(expected_field_type);
let record_field_type = printer.print_type(record_field_type);
let record_variant = printer.print_type(record_variant);
Expand Down Expand Up @@ -2530,7 +2530,7 @@ but no type in scope with that name."
}

TypeError::PrivateTypeLeak { location, leaked } => {
let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);

// TODO: be more precise.
// - is being returned by this public function
Expand Down Expand Up @@ -2859,7 +2859,7 @@ tuple has {} elements so the highest valid index is {}.",
}

TypeError::NotATuple { location, given } => {
let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);
let text = format!(
"To index into this value it needs to be a tuple, \
however it has this type:
Expand Down Expand Up @@ -3518,7 +3518,7 @@ Rename or remove one of them.",
}

TypeError::NotFnInUse { location, type_ } => {
let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);
let text = wrap_format!(
"In a use expression, there should be a function on \
the right hand side of `<-`, but this value has type:
Expand Down Expand Up @@ -3643,7 +3643,7 @@ so it cannot take the `use` callback function as a final argument.\n",
location,
actual_type: Some(actual),
} => {
let mut printer = Printer::new(names);
let mut printer = Printer::new_without_type_variables(names);
let text = wrap_format!(
"The function on the right hand side of `<-` \
has to take a callback function as its last argument. \
Expand Down
63 changes: 63 additions & 0 deletions compiler-core/src/type_/tests/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3345,3 +3345,66 @@ fn type_used_as_a_constructor_with_more_arguments() {
}"
);
}

#[test]
fn errors_type_printing_ignores_type_variables_from_other_function() {
assert_module_error!(
"
pub fn hello(a, b, c, d, e, f) { todo }

pub fn main() {
let x: Nil = []
}
"
);
}

#[test]
fn errors_type_printing_ignores_type_variables_from_constructor() {
assert_module_error!(
"
pub type Wibble(a, b, c, d, e, f) {
Wibble(value: a)
}

pub fn main() {
let x: Nil = []
}
"
);
}

#[test]
fn errors_type_printing_considers_type_variables_from_current_function() {
assert_module_error!(
"
pub fn wibble(a, b) {
let x: Nil = []
}
"
);
}

#[test]
fn errors_type_printing_considers_type_variables_from_current_function_with_return_value() {
assert_module_error!(
"
pub fn wibble(a, b) -> a {
let x: Nil = []
}
"
);
}

#[test]
fn errors_type_printing_considers_type_variables_from_current_function_and_ignores_from_other() {
assert_module_error!(
"
pub fn wobble(a, b, c, d, e) -> f { todo }

pub fn wibble(a, b) -> a {
let x: Nil = []
}
"
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
source: compiler-core/src/type_/tests/errors.rs
expression: "\npub fn wibble(a, b) {\n let x: Nil = []\n}\n"
---
----- SOURCE CODE

pub fn wibble(a, b) {
let x: Nil = []
}


----- ERROR
error: Type mismatch
┌─ /src/one/two.gleam:3:16
3 │ let x: Nil = []
│ ^^

Expected type:

Nil

Found type:

List(a)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
source: compiler-core/src/type_/tests/errors.rs
expression: "\npub fn wobble(a, b, c, d, e) -> f { todo }\n\npub fn wibble(a, b) -> a {\n let x: Nil = []\n}\n"
---
----- SOURCE CODE

pub fn wobble(a, b, c, d, e) -> f { todo }

pub fn wibble(a, b) -> a {
let x: Nil = []
}


----- ERROR
error: Type mismatch
┌─ /src/one/two.gleam:5:3
5 │ let x: Nil = []
│ ^^^^^^^^^^^^^^^

The type of this returned value doesn't match the return type
annotation of this function.

Expected type:

a

Found type:

List(a)

error: Type mismatch
┌─ /src/one/two.gleam:5:16
5 │ let x: Nil = []
│ ^^

Expected type:

Nil

Found type:

List(a)
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
source: compiler-core/src/type_/tests/errors.rs
expression: "\npub fn wibble(a, b) -> a {\n let x: Nil = []\n}\n"
---
----- SOURCE CODE

pub fn wibble(a, b) -> a {
let x: Nil = []
}


----- ERROR
error: Type mismatch
┌─ /src/one/two.gleam:3:3
3 │ let x: Nil = []
│ ^^^^^^^^^^^^^^^

The type of this returned value doesn't match the return type
annotation of this function.

Expected type:

a

Found type:

List(a)

error: Type mismatch
┌─ /src/one/two.gleam:3:16
3 │ let x: Nil = []
│ ^^

Expected type:

Nil

Found type:

List(a)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
source: compiler-core/src/type_/tests/errors.rs
expression: "\npub type Wibble(a, b, c, d, e, f) {\n Wibble(value: a)\n}\n\npub fn main() {\n let x: Nil = []\n}\n"
---
----- SOURCE CODE

pub type Wibble(a, b, c, d, e, f) {
Wibble(value: a)
}

pub fn main() {
let x: Nil = []
}


----- ERROR
error: Type mismatch
┌─ /src/one/two.gleam:7:16
7 │ let x: Nil = []
│ ^^

Expected type:

Nil

Found type:

List(a)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
source: compiler-core/src/type_/tests/errors.rs
expression: "\npub fn hello(a, b, c, d, e, f) { todo }\n\npub fn main() {\n let x: Nil = []\n}\n"
---
----- SOURCE CODE

pub fn hello(a, b, c, d, e, f) { todo }

pub fn main() {
let x: Nil = []
}


----- ERROR
error: Type mismatch
┌─ /src/one/two.gleam:5:16
5 │ let x: Nil = []
│ ^^

Expected type:

Nil

Found type:

List(a)
Loading