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.
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