Crystal: 'has no types' bug when calling 'TypeNode#constant' on a generic class

Created on 28 Feb 2018  路  7Comments  路  Source: crystal-lang/crystal

Crystal v0.24.1
macOS 10.13.3

https://play.crystal-lang.org/#/r/3nmq

class Thing(T)
  MY_CONSTANT = "Such a good constant"

  macro inherited
    {% p @type.ancestors.first.constant(:MY_CONSTANT) %}
  end
end

class Something < Thing(String)
end

Results in:

Error in line 9: expanding macro

in line 5: BUG: Thing(String) has no types

This works for regular classes and abstract classes but results in that compiler bug when used with a generic class or a generic abstract class.

bug compiler

All 7 comments

I had a similar bug for virtual types.

For example, the following:

module Foo
  macro included
    {% if [email protected]_constant? :BAR %}
      BAR = [] of _
    {% end %}

    macro bar(bar)
      \{% BAR << bar.id %}
    end

    macro inherited
      \{% if [email protected]_constant? :BAR %}
        BAR = [] of _
      \{% end %}
      \{% for bar in BAR %}
        bar \{{ bar }}
      \{% end %}
    end
  end

  def bar
    {% for bar in @type.constant(:BAR) %}
      puts {{bar.stringify}}
    {% end %}
  end
end

class Baz
  include Foo
  bar hello
end

class Qux < Baz
  bar world
end

class Quux < Baz
  bar universe
end

puts Qux.new.bar
puts Baz.new.bar
puts Quux.new.bar

compiles and works as expected.

However, when upcasting, the bug appears:

puts Qux.new.as(Baz).bar # => BUG: Baz+ has no types

Crystal 0.27.0

Bump, experiencing this as well.

Was able to narrow it down to https://github.com/crystal-lang/crystal/blob/master/src/compiler/crystal/types.cr#L1715 by adding a types method to various subclasses, and this one was the one that raised. However I'm not sure where to go from here.

Er nvm. I don't really know what I'm doing. @asterite any ideas on this?

Still happening


Crystal 0.31.1 on MacOS

$ crystal --version
Crystal 0.31.1 (2019-10-02)

LLVM: 8.0.1
Default target: x86_64-apple-macosx

 5 | {% p @type.ancestors.first.constant(:MY_CONSTANT) %}
                                ^-------
Error: BUG: Thing(String) has no types

FWIW it doesn't seem to happen if calling it directly on the TypeNode.

https://play.crystal-lang.org/#/r/8s8q

abstract struct Parent
  FOO = "BAR"
end

struct Child(T) < Parent
end

{{pp Parent.constant("FOO")}} # => "BAR"
{{pp Child.constant("FOO")}} # => nil

Maybe a clue is that the second call returns nil, shouldn't it inherit the constant?

The constant is defined in Parent, not Child

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ArthurZ picture ArthurZ  路  3Comments

will picture will  路  3Comments

nabeelomer picture nabeelomer  路  3Comments

costajob picture costajob  路  3Comments

Sija picture Sija  路  3Comments