Skip to content

Instantiate generics in mutually recursive functions before unification#5071

Open
abs0luty wants to merge 4 commits into
gleam-lang:mainfrom
abs0luty:fix-type-inference
Open

Instantiate generics in mutually recursive functions before unification#5071
abs0luty wants to merge 4 commits into
gleam-lang:mainfrom
abs0luty:fix-type-inference

Conversation

@abs0luty

@abs0luty abs0luty commented Oct 24, 2025

Copy link
Copy Markdown
Contributor

@abs0luty abs0luty changed the title Preserve generic type parameters when constructors or functions are used without explicit annotations Preserve generic type parameters when constructors, functions are used without explicit annotations Oct 24, 2025
@abs0luty abs0luty changed the title Preserve generic type parameters when constructors, functions are used without explicit annotations Preserve generic parameters when constructors, functions are used without explicit annotations Oct 24, 2025
@abs0luty
abs0luty force-pushed the fix-type-inference branch 2 times, most recently from 96d4132 to 980e01e Compare October 24, 2025 17:37
@abs0luty abs0luty changed the title Preserve generic parameters when constructors, functions are used without explicit annotations Fix type inference for functions, constructors without explicit annotations. Oct 24, 2025
@abs0luty abs0luty changed the title Fix type inference for functions, constructors without explicit annotations. Fix type inference for functions, constructors without explicit annotations Oct 24, 2025
@abs0luty
abs0luty force-pushed the fix-type-inference branch 3 times, most recently from 0761e59 to d1a7ec5 Compare October 31, 2025 06:19
@abs0luty abs0luty changed the title Fix type inference for functions, constructors without explicit annotations Fix generic inference by instantiating annotations and storing inferred types Nov 24, 2025
@abs0luty
abs0luty force-pushed the fix-type-inference branch 2 times, most recently from 1e806ed to 62de43d Compare December 3, 2025 20:18
@abs0luty abs0luty changed the title Fix generic inference by instantiating annotations and storing inferred types Instantiate generics in mutually recursive functions before unification Dec 3, 2025
@giacomocavalieri

Copy link
Copy Markdown
Member

Hello! Would you mind rebasing on main to fix the conflicts?

@abs0luty

Copy link
Copy Markdown
Contributor Author

@giacomocavalieri Only now noticed your message, sure!

@abs0luty
abs0luty force-pushed the fix-type-inference branch 2 times, most recently from dcd08c8 to b4a9c9b Compare February 1, 2026 11:20
@giacomocavalieri

Copy link
Copy Markdown
Member

Hello! It looks like tests are failing, would you mind having a look at those?

@ankddev

ankddev commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

They all fail with this compile error:

error: unnecessary qualification
Error:     --> language-server/src/code_action.rs:1639:51
     |
1639 |     fn visit_typed_function(&mut self, fun: &'ast ast::TypedFunction) {
     |                                                   ^^^^^^^^^^^^^^^^^^
     |
     = note: `-D unused-qualifications` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(unused_qualifications)]`
help: remove the unnecessary path segments
     |
1639 -     fn visit_typed_function(&mut self, fun: &'ast ast::TypedFunction) {
1639 +     fn visit_typed_function(&mut self, fun: &'ast TypedFunction) {
     |

@abs0luty
abs0luty force-pushed the fix-type-inference branch 3 times, most recently from fc936f1 to e2a49ae Compare March 17, 2026 13:52

@ankddev ankddev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some notes about changelog entry

Comment thread CHANGELOG.md Outdated
Comment thread CHANGELOG.md Outdated
@abs0luty
abs0luty force-pushed the fix-type-inference branch from e2a49ae to c1a4864 Compare March 29, 2026 09:22
Comment thread CHANGELOG.md Outdated

@giacomocavalieri giacomocavalieri left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello! I left a little comment

@abs0luty
abs0luty force-pushed the fix-type-inference branch 4 times, most recently from 3084716 to b5bf662 Compare April 5, 2026 08:16
abs0luty added 3 commits May 15, 2026 18:12
…ns before unification

```gleam
pub type Test(a) { Test(a) }
pub fn it(value: Test(a)) { it2(value) }
pub fn it2(value: Test(a)) -> Test(a) { it(value) }

pub fn main() { it(Test(1)) }
```

Before this change the compiler compared generic "sketches" directly to inferred types
in mutually recursive calls, causing false mismatches when generics behaved rigidly.

After the patch the compiler instantiates generics (based on annotations or inferred
concrete types) and updates the environment so mutually recursive functions unify correctly.

This resolves spurious type-errors in recursive scenarios.
```
fn wibble(a, b, c) {
   ↑
  let x: a = todo
  fn(a: b, b: c) -> d {
    todo
  }
}
```

After action:
```diff
- fn wibble(a: e, b: f, c: g) -> fn(b, c) -> h
+ fn wibble(a: e, b: f, c: g) -> fn(b, c) -> d
                                             ^ original name is preserved
```

When the "add annotations" code-action is used, the compiler now retains the
original type-variable names from the user's annotation instead of replacing them
with fresh or default names.

This ensures that added annotations reflect the user's naming exactly and prevents
confusing or misleading variable renaming.
@abs0luty
abs0luty force-pushed the fix-type-inference branch from b5bf662 to d6bd688 Compare May 15, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Type inference issue expected Test(a) but found Test(a) Unbound type variable in top level definition after type inference

4 participants