HaxeFoundation / HaxeFoundation/haxe
Inconsistent overload resolution with lambda vs function syntax
- 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
Assessment
This issue has not been assessed yet.