There is a bug with automatic casting of symbols to enum values when using named arguments defined in multiple overloads of a method.
Reproducible example:
enum Foo
FOO
end
def foo(unused, foo : Foo)
end
def foo(foo : Foo)
end
foo(foo: :FOO) # ambiguous call, implicit cast of :FOO matches all of Foo
Citing @asterite from https://github.com/crystal-lang/crystal/pull/6314#issuecomment-428962280 :
If I remember correctly, the problem is in these lines:
The logic is incorrect, it only works if there are no named arguments and all the defs that match the signature, ignoring type restrictions, is not well computed. Someone should fix that logic and it will start working well... I think. But I don't have time to tackle this.
@straight-shoota I can work on this, the output from the shared example should be the execution of method def foo(foo : Foo) without raising any error?
I spent a lot of time on this but I didn't manage to find where this method is called twice: https://github.com/crystal-lang/crystal/blob/master/src/compiler/crystal/types.cr#L1358 I assume that what was causing the issue for autocasting Symbols.
I may be wrong but I was following the logic so far and call_error is responsible for triggering the lookup with literals (for autocasting) by raising this exception: https://github.com/crystal-lang/crystal/blob/master/src/compiler/crystal/semantic/call_error.cr#L249 (so far no issue found in that file)
For reference those PRs where useful:
Hey, I think I know why it happens but I don't have time to fix it nor explain it. Sorry.
I'll try to investigate more anyway it may help me to understand the code base.
Most helpful comment
@straight-shoota I can work on this, the output from the shared example should be the execution of method
def foo(foo : Foo)without raising any error?