"no overload matches" compile error on seemly matching constructor signatures

I have the following definitions (clipping out parts not relevant):

abstract class Change
  ...
  def initialize(@model : ModelInterface, @unit : Unit)
  end
  ...
  abstract class NoOption < Change
    ...
  end
  ...
end

class Change::Outline < Change::NoOption
  ...
end

module ModelInterface
  ...
end

class LanguageModel
  include ModelInterface
  ...
end

abstract class Unit
  ...
end

I have some code that looks like:

@change_class.as(Change::NoOption).new @model, @unit

When I attempt to compile I get the following error:

 78 | @change_class.as(Change::NoOption).new @model, @unit
                                         ^--
Error: no overload matches 'Change::Outline#new' with types LanguageModel, Unit+

Overloads are:
 - Change.new(model : ModelInterface, unit : Unit)

Iā€™m not clear on what the mismatch is. My constructor is defined as taking a ModelInterface and some subclass of Unit. The error indicates I am sending it a LanguageModel (which ModelInterface is mixed into) and some subclass of Unit. What I am I missing? Those seem to match.

@change_class.as(Change::NoOption) casts @change_class to an instance of Change::NoOption, so your code is trying to call an instance method (#new). The constructor would be a class method (.new).

You might want to cast to the metaclass of Change::Option as @change_class.as(Change::NoOption.class).

1 Like

:man_facepalming: - I might have eventually seen that but you saved me a lot of time. I was so focused on if the args were matching I missed that was restricting the type incorrectly. I even had similar code elsewhere that was doing it right but somehow missed it here. Thanks!