Crystal: Module validation failed: Stored value type does not match pointer operand type!

Created on 4 Aug 2018  Â·  5Comments  Â·  Source: crystal-lang/crystal

Hello. When I was playing with a code I received a message:

Module validation failed: Stored value type does not match pointer operand type!
  store i16 0, i32* %0, !dbg !13
 i32Stored value type does not match pointer operand type!
  store i64 0, i32* %1, !dbg !14
 i32Call parameter type does not match function signature!
  %33 = load i32, i32* %32, !dbg !27
 i16  %34 = call %"IO::FileDescriptor"* @"*UInt16@Int#inspect<IO::FileDescriptor>:IO::FileDescriptor"(i32 %33, %"IO::FileDescriptor"* %io), !dbg !27
Call parameter type does not match function signature!
  %38 = load i32, i32* %37, !dbg !27
 i64  %39 = call %"IO::FileDescriptor"* @"*UInt64@Int#inspect<IO::FileDescriptor>:IO::FileDescriptor"(i32 %38, %"IO::FileDescriptor"* %io), !dbg !27
 (Exception)
  from ???
[… dupes skipped …]
  from ???
Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues

The code to reproduce:

class AnotherClass(T)
  @sum : T
  @count : UInt64

  def initialize(val)
    @sum = 0
    @count = 0
  end
end

class SomeClass(T)
  class AnotherClass(T) < AnotherClass(T)
    def initialize(el : Array(T))
      super
    end

    def initialize(el : T)
      @sum = 0
      @count = 0
    end
  end

  @values = [] of AnotherClass(T)

  def initialize(values : Array(Array(T) | T) = [] of T)
    @values = values.map { |el| AnotherClass(T).new(el) }
    puts @values
  end
end

bar = SomeClass(UInt16).new([[1_u16, 2_u16]])

OS:

Debian GNU/Linux 9.5 (stretch)

Crystal version:

Crystal 0.25.1 [b782738ff] (2018-06-27)

LLVM: 4.0.0
Default target: x86_64-unknown-linux-gnu

The bug also can be reproduced on master branch with a detailed backtrace:

Crystal 0.25.1+86 [d454f6973] (2018-08-04)

LLVM: 4.0.1
Default target: x86_64-pc-linux-gnu
Module validation failed: Stored value type does not match pointer operand type!
  store i16 0, i32* %0, !dbg !13
 i32Stored value type does not match pointer operand type!
  store i64 0, i32* %1, !dbg !14
 i32Call parameter type does not match function signature!
  %33 = load i32, i32* %32, !dbg !27
 i16  %34 = call %"IO::FileDescriptor"* @"*UInt16@Int#inspect<IO::FileDescriptor>:IO::FileDescriptor"(i32 %33, %"IO::FileDescriptor"* %io), !dbg !27
Call parameter type does not match function signature!
  %38 = load i32, i32* %37, !dbg !27
 i64  %39 = call %"IO::FileDescriptor"* @"*UInt64@Int#inspect<IO::FileDescriptor>:IO::FileDescriptor"(i32 %38, %"IO::FileDescriptor"* %io), !dbg !27
 (Exception)
  from /tmp/crystal/src/llvm/module.cr:78:9 in 'verify'
  from /tmp/crystal/src/compiler/crystal/codegen/codegen.cr:343:9 in 'finish'
  from /tmp/crystal/src/compiler/crystal/codegen/codegen.cr:67:7 in 'codegen'
  from /tmp/crystal/src/compiler/crystal/codegen/codegen.cr:63:5 in 'codegen:debug:single_module'
  from /tmp/crystal/src/compiler/crystal/compiler.cr:22:7 in 'codegen'
  from /tmp/crystal/src/compiler/crystal/compiler.cr:145:16 in 'compile'
  from /tmp/crystal/src/compiler/crystal/command.cr:260:7 in 'compile'
  from /tmp/crystal/src/compiler/crystal/command.cr:179:14 in 'run_command'
  from /tmp/crystal/src/compiler/crystal/command.cr:87:7 in 'run'
  from /tmp/crystal/src/compiler/crystal/command.cr:48:5 in 'run'
  from /tmp/crystal/src/compiler/crystal/command.cr:47:3 in 'run'
  from /tmp/crystal/src/compiler/crystal.cr:8:1 in '__crystal_main'
  from /tmp/crystal/src/crystal/main.cr:104:5 in 'main_user_code'
  from /tmp/crystal/src/crystal/main.cr:93:7 in 'main'
  from /tmp/crystal/src/crystal/main.cr:133:3 in 'main'
  from __libc_start_main
  from _start
  from ???
Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues
bug compiler

All 5 comments

The code works if you redeclare @sum : T and @count : UInt64 in SomeClass::AnotherClass (carc.in link here).

Minified example:

class A(T)
  @count : UInt64

  def initialize(val)
    @count = 0
  end
end

class C(T) < A(T)
  def initialize(el : Array(T))
    super
  end

  def initialize(el : T)
    @count = 1
  end
end

class B(T)
  @values = [] of C(T)

  def initialize(values : Array(T))
    @values = values.map { |el| C(T).new(el) }
  end
end

bar = B(UInt16).new([1_u16, 2_u16])

This is probably an issue with automatic casting, which doesn't get activated with @count = 1 in C(T)#initialize in the above example - I can remove @count : UInt64 and it works, or change it to @count : UInt16 to have it still break. See #6074 for the PR.

I'm not sure if this is intended behaviour or not, to not have automatic casting "carry over" with instance vars during inheritance. If this is intended behaviour, the LLVM error message should be caught as a compile error or something. (CC @asterite)

Thank you for your proposal! When you work in the night almost falling asleep strange things happen. Cut here, paste there, build, WTF? Next day you read yesterdays code and think "What idiot wrote that?". :)

See #6074 for the PR

Thanks, that is really great description!

@serge-name Ah, fair enough. Sorry for the statement at the end, I thought it came off as a bit harsh (which is why I removed it). But seriously though, that code is so obscure I had to comment on it.

Never mind. Let's make Crystal more stable and shiny :)

Still being reproduced on

Crystal 0.27.0 [c9d1eef8f] (2018-11-01)

LLVM: 4.0.0
Default target: x86_64-unknown-linux-gnu
Was this page helpful?
0 / 5 - 0 ratings