crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.35k stars 1.62k forks source link

Interpreter: Cast from Crystal::TypeDefType to Crystal::PointerInstanceType failed #14151

Open mdwagner opened 9 months ago

mdwagner commented 9 months ago

Bug Report

First discovered in lexbor shard when trying out interpreter, these Lib bindings fail to run:

# src/lexbor/lib.cr
type TokenAttrT = TokenAttr*
type HtmlTokenT = HtmlToken*

Error message:

Cast from Crystal::TypeDefType to Crystal::PointerInstanceType failed

However, if I replace type with alias, it works:

# src/lexbor/lib.cr
alias TokenAttrT = TokenAttr*
alias HtmlTokenT = HtmlToken*

Crystal version:

Crystal 1.10.1 [c6f3552f5] (2023-10-13)

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

Crystal interpreter version:

Crystal 1.11.0-dev [e00a0a4f3] (2023-12-24)

LLVM: 17.0.4
Default target: x86_64-redhat-linux-gnu

OS: Fedora 39 x86_64

HertzDevil commented 8 months ago

Reduced:

lib Lib
  type Foo = Int32*
end

x = Pointer(Int32).new(0x1234_u64).as(Lib::Foo)
x.value     # pointer_get
x.value = 1 # pointer_set

Some other related pointer primitives break in normal codegen too:

lib Lib
  type Foo = Int32*
end

x = Pointer(Int32).new(0x1234_u64).as(Lib::Foo)
x + 1_i64        # pointer_add
x - x            # pointer_diff
x.realloc(8_u64) # pointer_realloc

# pointer_malloc has the same issue, but that is fine because
# typedefs cannot access the original type's class methods

That said, type should only be used for opaque types, so if you find yourself expecting that a TokenAttrT can be dereferenced to a TokenAttr, maybe those types aren't so opaque after all?