crystal icon indicating copy to clipboard operation
crystal copied to clipboard

Add detail to errors involving automatic casting of symbols

Open hanyuone opened this issue 6 years ago • 4 comments

cc @straight-shoota

When a user calls a function which autocasts a symbol literal as an enum and the symbol name doesn't exist:

enum Foo
  Bar
  Baz
  Quux
end

def foo(arg : Foo)
end

foo(:far) # :far doesn't exist in Foo

The error message is unhelpful, and while it does address the fact that foo() doesn't work with Symbol, it doesn't detect the automatic casting:

Error in line 10: no overload matches 'foo' with type Symbol
Overloads are:
 - foo(arg : Foo)

An extra portion could be added onto the end of this error, listing possible typos that the user may have entered:

Do you mean:
- :bar (Foo::Bar)
- :gar (FooAgain::Gar)

hanyuone avatar Jan 07 '19 14:01 hanyuone

@asterite I saw the source code of autocasting and I assume it could be easy to raise proper error in this case? Also please consider def foo(arg : Foo | String) case (i.e. with union argument where Enum is a part of this union). Usecase: https://carc.in/#/r/6er7 (need better error here)

vladfaust avatar Mar 03 '19 22:03 vladfaust

This is actually a bit hard to implement. The above only considers a method with a single argument. What happens if you have multiple arguments? For example:

enum Foo
  Bar
  Baz
  Quux
end

def foo(x : String, arg : Foo)
end

foo(1, :far)

Right now you get:

Error in foo.cr:10: no overload matches 'foo' with types Int32, Symbol
Overloads are:
 - foo(x : String, arg : Foo)

foo(1, :far)
^~~

But what, should it also say that the symbol won't match, and list all possible values? What happens if there are multiple arguments that need to be autocast? Should this be shown below the Overloads list?

asterite avatar May 07 '19 20:05 asterite

Removing symbols and using :foo notation only as symbol shorthand would allow this, I think the correct discussion of that is #6736.

RX14 avatar May 08 '19 16:05 RX14

But what, should it also say that the symbol won't match, and list all possible values?

If the argument to be autocast is the first one that fails an overload match, yes, otherwise some other error will be shown as part of #11106. Say:

enum Foo
  Bar
end

def foo(x : Int32, y : Foo); end

# Error: no overload matches
# Note: failed to match argument #2 against parameter `y : Foo`
# Did you mean `:bar`?
foo(1, :bat)

# Error: no overload matches
# Note: failed to match argument #1 against parameter `x : Int32`
foo("", :bat)

HertzDevil avatar Jul 10 '22 20:07 HertzDevil