Enums methods with super/previous_def

I’m trying to redefine Enum.parse? but re-use the previous parsing in order to add more possible parsable values. The issue is that neither previous_def nor super works, for reasons that make sense. previous_def doesn’t work because it’s not really meant for this situation (rather, it’s used when you’ve already defined the method for the particular type), and super doesn’t work because of how Enum works (see this issue). However, that leaves me with no choice but to reimplement the supertype method, which isn’t ideal. Here’s an example with super:

enum Something
  Alphabet
  Numeric

  def self.parse?(string : String) : self?
    result = super string # => Error: can't use Enum in unions yet, use a more specific type

    if result.nil?
      case string
      when "abc"
        result = Alphabet
      when "123"
        result = Numeric
      end
    end

    result
  end
end

# I want these both to work
s = Something.parse? "abc"
t = Something.parse? "numeric"

p! s

I think the compile-time error message is indicative of the kind of problem it is, but not the underlying issue (which is that super doesn’t work on Enum because of how Enum works).

Really, the reason I’m explaining all this is that I hope I’m missing something. Is there a solution I haven’t considered?

It appears the only thing preventing Enum.parse? being called via super is its return type restriction self? which triggers the union error. This is even incorrect, be cause self in this context isn’t Enum, it’s the enum type Something which should be fine to use in unions.

https://carc.in/#/r/cnvg

I suppose a simple fix for this would be to remove the return type restriction from Enum.parse?. Or maybe refactor that method so that it is only defined on inheriting types, not on Enum itself. That’s actually something that could apply to all of Enum's class methods.

1 Like

Do you think it would be worth putting in a PR for this, then? Given that it’ll only really involve changing a type signature (or maybe using macro inherited) and then presumably adding some sort of test, I think I could handle it.

1 Like