Crystal: Compiler bug redefining an enum's initialize

Created on 30 Dec 2018  路  8Comments  路  Source: crystal-lang/crystal

Code:

enum Foo
  FOO = 1

  def initialize
  end
end

Compiler error:

Missing hash key: Foo (KeyError)
  from src/hash.cr:126:9 in 'fetch'
  from src/hash.cr:62:5 in '[]'
  from src/compiler/crystal/semantic/type_guess_visitor.cr:1131:9 in 'visit'
  from src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from src/compiler/crystal/semantic/semantic_visitor.cr:105:27 in 'visit'
  from src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from src/compiler/crystal/syntax/ast.cr:169:27 in 'accept_children'
  from src/compiler/crystal/syntax/visitor.cr:28:11 in 'accept'
  from src/compiler/crystal/semantic/hooks.cr:26:7 in 'visit_with_finished_hooks'
  from src/compiler/crystal/semantic/type_declaration_processor.cr:140:5 in 'process'
  from src/compiler/crystal/semantic.cr:70:7 in 'top_level_semantic'
  from src/compiler/crystal/semantic.cr:22:23 in 'semantic'
  from src/compiler/crystal/compiler.cr:152:7 in 'compile'
  from src/compiler/crystal/command/eval.cr:29:14 in 'eval'
  from src/compiler/crystal/command.cr:82:7 in 'run'
  from src/compiler/crystal/command.cr:46:5 in 'run'
  from src/compiler/crystal/command.cr:45:3 in 'run'
  from src/compiler/crystal.cr:8:1 in '__crystal_main'
  from src/crystal/main.cr:97:5 in 'main_user_code'
  from src/crystal/main.cr:86:7 in 'main'
  from src/crystal/main.cr:106:3 in 'main'
  from __libc_start_main
  from _start
  from ???

Redefining initialize in an enum type should probably be a syntax error.

bug compiler lang

Most helpful comment

Here's a fix to self.new not working:

diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr
index 4dcdb04ef..19d641430 100644
--- a/src/compiler/crystal/types.cr
+++ b/src/compiler/crystal/types.cr
@@ -2636,7 +2636,7 @@ module Crystal
       super(program, namespace, name)

       add_def Def.new("value", [] of Arg, Primitive.new("enum_value", @base_type))
-      metaclass.as(ModuleType).add_def Def.new("new", [Arg.new("value", type: @base_type)], Primitive.new("enum_new", self))
+      metaclass.as(ModuleType).add_def Def.new("new", [Arg.new("value", restriction: Path.global(@base_type.to_s))], Primitive.new("enum_new", self))
     end

     def parents

All 8 comments

An alternative is to make it work but require to invoke super or another initialize. But a new constructor can also be done with self.new, so it might be better to just give an error here, as you say.

But self.new can't override the implicit .new method.

I also noticed that the implicit methods .new and #value are not documented.

But self.new can't override the implicit .new method

It's probably a bug.

I also noticed that the implicit methods .new and #value are not documented.

Right, because they are generated each time for every enum, they are hardcoded in the code. The only way we could document them is by adding the docs in the compiler's code.

Here's a fix to self.new not working:

diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr
index 4dcdb04ef..19d641430 100644
--- a/src/compiler/crystal/types.cr
+++ b/src/compiler/crystal/types.cr
@@ -2636,7 +2636,7 @@ module Crystal
       super(program, namespace, name)

       add_def Def.new("value", [] of Arg, Primitive.new("enum_value", @base_type))
-      metaclass.as(ModuleType).add_def Def.new("new", [Arg.new("value", type: @base_type)], Primitive.new("enum_new", self))
+      metaclass.as(ModuleType).add_def Def.new("new", [Arg.new("value", restriction: Path.global(@base_type.to_s))], Primitive.new("enum_new", self))
     end

     def parents

@asterite could you PR that?

@RX14 Sure, it's already included in the PR that fixes this.

Yeah, I just saw that :)

Was this page helpful?
0 / 5 - 0 ratings