HaxeFoundation / HaxeFoundation/haxe

Inconsistent overload resolution with lambda vs function syntax

Open
#12,667 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Haxe
Stars
6.9k
Forks
715
Avg merge
2d 2h
Merged PRs (30d)
11

Description

The problem is that any function can be passed as `() -> Void`, so if you have two overloads, `() -> String` and `() -> Void`, an argument with type `() -> String` works for both of them. Understandably, this gives an ambiguity error.

However, for some reason the ambiguity is "resolved" when using a lambda with an explicit return, and it doesn't always pick the correct thing:

```haxe
extern inline overload function create(f:() -> String) {
trace("String");
}

extern inline overload function create(f:() -> Void) {
trace("Void");
}

function main() {
// allowed (expected)
create(() -> {}); // Void
create(() -> { return; }); // Void
create(function() { return; }); // Void

// allowed (should fail?)
create(() -> return ""); // String
create(() -> { return ""; }); // String
create(() -> { return throw ""; }); // String ??

// error (unexpected?)
create(function() {});

// error (expected)
create(() -> "");
create(function() return "");
create(function() { return ""; });
create(function() { return throw ""; });
}
```
hxcoro currently has code like this, where it compiles but would break if `() -> { return ... }` is swapped for `function() { return ... }`: https://github.com/HaxeFoundation/hxcoro/blob/9acb73baf65fbaab0d8d26b57ea30475fb01c4c9/tests/src/generators/TestAsyncGenerator.hx#L85-L90

#12661 aimed to address this by preferring `() -> Void` for this example where the type is $\bot$, but that results in weird edge cases and inconsistencies comparing to abstract operators/casts. In the end, quoting @Simn:
> at the end of the day this is a pointless discussion because Haxe allows assigning anything to a Void return type, which actually makes it a top type, not a bottom type. So I suppose this is working as intended right now and the solution is indeed to avoid this inference problem.

It seems to me like `create(() -> return "")` should match the error given by `create(function() return "")`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.