# 1.6.2 Compilation error

**URL:** <https://forum.crystal-lang.org/t/1-6-2-compilation-error/5072>\
**Category:** Crystal Contrib\
**Created:** [November 4, 2022, 11:48am UTC](https://forum.crystal-lang.org/t/1-6-2-compilation-error/5072 "2022-11-04T11:48:29Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ragmaanir](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ragmaanir/32/1174_2.png) [@Ragmaanir](https://forum.crystal-lang.org/u/Ragmaanir)\
**Post date:** [November 4, 2022, 11:48am UTC](https://forum.crystal-lang.org/t/1-6-2-compilation-error/5072/1 "2022-11-04T11:48:29Z")

</div>

This code compiles in 1.6.1 without errors:

```crystal
abstract class Migration
  module Meta
    include Comparable(Meta)

    abstract def timestamp : String

    def <=>(other : self)
      timestamp <=> other.timestamp
    end
  end

  macro inherited
    def self.timestamp : String
      "dontcare"
    end
  end

  extend Meta

  def self.all : Array(Migration.class)
    [M1] of Migration.class
  end
end

class M1 < Migration
end

Migration.all.sort

```

See [carc.in](https://carc.in/#/r/e07p)

But with 1.6.2 it fails with this compilation error:

```auto
 199 | v = v1 <=> v2
                  ^-
Error: expected argument #1 to 'M1.<=>' to be Migration::Meta, not Migration+.class

Overloads are:
 - Migration::Meta#<=>(other : self)

```

The fix is to change the `<=>` signature:

```auto
def <=>(other : self | Migration.class) # here
  timestamp <=> other.timestamp
end

```

I don’t know why exactly the error occurs and can’t tell whether this is expected behavior or not, so i’m asking here first (My other projects compile and run fine btw, this is the only issue i found).

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [November 4, 2022, 12:12pm UTC](https://forum.crystal-lang.org/t/1-6-2-compilation-error/5072/2 "2022-11-04T12:12:43Z")

</div>

Reduced:

```crystal
class Migration
  module Meta
    def foo(other : self)
    end
  end

  extend Meta
end

class M1 < Migration
end

M1.foo(M1) # Error: no overload matches 'M1.foo' with type M1.class

```

This already fails on 1.6.1 (and earlier), but it can be worked around by an explicit cast to the virtual metaclass:  
`M1.as(Migration.class).foo(M1.as(Migration.class))`

On 1.6.2 this work around does not work. So I guess 1.6.2 broke one edge case that happened to work before, while other similar cases did not even work.

---

<div class="post-metadata">

**Author:** ![beta-ziliani](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/beta-ziliani/32/1821_2.png) [@beta-ziliani](https://forum.crystal-lang.org/u/beta-ziliani)\
**Post date:** [November 4, 2022, 12:13pm UTC](https://forum.crystal-lang.org/t/1-6-2-compilation-error/5072/3 "2022-11-04T12:13:04Z")

</div>

The culprit is [Fix `VirtualMetaclassType#implements?` to ignore base\_type by straight-shoota · Pull Request #12632 · crystal-lang/crystal · GitHub](https://github.com/crystal-lang/crystal/pull/12632)

---

<div class="post-metadata">

**Author:** ![beta-ziliani](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/beta-ziliani/32/1821_2.png) [@beta-ziliani](https://forum.crystal-lang.org/u/beta-ziliani)\
**Post date:** [November 4, 2022, 12:31pm UTC](https://forum.crystal-lang.org/t/1-6-2-compilation-error/5072/4 "2022-11-04T12:31:22Z")

</div>

With the revert of #12632 the workaround works. (Note: there’s a typo in your workaround, the second `.as(...)` should go inside the parens).

---

<div class="post-metadata">

**Author:** ![HertzDevil](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hertzdevil/32/1023_2.png) [@HertzDevil](https://forum.crystal-lang.org/u/HertzDevil)\
**Post date:** [November 4, 2022, 1:03pm UTC](https://forum.crystal-lang.org/t/1-6-2-compilation-error/5072/5 "2022-11-04T13:03:32Z")

</div>

[`self` in restrictions always refers to the instance type](https://crystal-lang.org/reference/1.6/syntax_and_semantics/type_restrictions.html#self-restriction) of the type where the def is instantiated, so this example is not supposed to work; the restriction _must_ be `Meta` itself. The same goes for `#<=>` in the original example.

---

<div class="post-metadata">

**Author:** ![beta-ziliani](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/beta-ziliani/32/1821_2.png) [@beta-ziliani](https://forum.crystal-lang.org/u/beta-ziliani)\
**Post date:** [November 4, 2022, 1:49pm UTC](https://forum.crystal-lang.org/t/1-6-2-compilation-error/5072/6 "2022-11-04T13:49:51Z")

</div>

You’re right, the current behavior seems correct then.

There are two possible fixes to the original code: change `self` with `self.class` in `Meta`, or change everything to be `Meta` as in:

```nohighlight
abstract class Migration
  module Meta
    include Comparable(Meta)

    abstract def timestamp : String

    def <=>(other : Meta)
      timestamp <=> other.timestamp
    end
  end

  macro inherited
    def self.timestamp : String
      "dontcare"
    end
  end

  extend Meta

  def self.all : Array(Meta)           
    [M1] of Meta           
  end
end

class M1 < Migration
end

Migration.all.sort

```

---

<div class="post-metadata">

**Author:** ![beta-ziliani](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/beta-ziliani/32/1821_2.png) [@beta-ziliani](https://forum.crystal-lang.org/u/beta-ziliani)\
**Post date:** [November 4, 2022, 1:52pm UTC](https://forum.crystal-lang.org/t/1-6-2-compilation-error/5072/7 "2022-11-04T13:52:39Z")

</div>

Alternatively, you can parametrize `Meta` and then `extend Meta(Migration.class)`.
