struct MyStruct
end
struct SubStruct < MyStruct
end
struct SubSubStruct < SubStruct
end
SubSubStruct.new as SubStruct
Bug: trying to upcast SubStruct <- SubSubStruct
[5698614] ???
[9807886] ???
[9736963] ???
[9538525] ???
[8301014] ???
[13044467] ???
[12711198] ???
[5696909] ???
[12660264] main +40
[140059539994384] __libc_start_main +240
[5673001] _start +41
[0] ???
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
Duplicate of...
just kidding! ;)
The problem is around here
@BlaXpirit I think that comment was for the other issue regarding blocks.
This is kind of hard to fix right now until we decide what to do with struct inheritance, so you'll have to wait a bit.
Why do you need to upcast a struct like that?
I just have a complex inheritance hierarchy for tiny objects that I would prefer to be structs. I don't have a great example to support this.
You mean, you found out that it crashes if you do as SubStruct but you don't actually need to do that in your code?
struct SF::Event (4 bytes)
├─╴struct SF::SensorEvent (24 bytes)
│ └─╴struct SF::Event::SensorChanged (24 bytes)
├─╴struct SF::TouchEvent (20 bytes)
│ ├─╴struct SF::Event::TouchEnded (20 bytes)
│ ├─╴struct SF::Event::TouchMoved (20 bytes)
│ └─╴struct SF::Event::TouchBegan (20 bytes)
├─╴struct SF::JoystickConnectEvent (12 bytes)
│ ├─╴struct SF::Event::JoystickDisconnected (12 bytes)
│ └─╴struct SF::Event::JoystickConnected (12 bytes)
├─╴struct SF::JoystickMoveEvent (20 bytes)
│ └─╴struct SF::Event::JoystickMoved (20 bytes)
├─╴struct SF::JoystickButtonEvent (16 bytes)
│ ├─╴struct SF::Event::JoystickButtonReleased (16 bytes)
│ └─╴struct SF::Event::JoystickButtonPressed (16 bytes)
├────╴struct SF::Event::MouseLeft (4 bytes)
├────╴struct SF::Event::MouseEntered (4 bytes)
├─╴struct SF::MouseMoveEvent (16 bytes)
│ └─╴struct SF::Event::MouseMoved (16 bytes)
├─╴struct SF::MouseButtonEvent (20 bytes)
│ ├─╴struct SF::Event::MouseButtonReleased (20 bytes)
│ └─╴struct SF::Event::MouseButtonPressed (20 bytes)
├─╴struct SF::MouseWheelScrollEvent (24 bytes)
│ └─╴struct SF::Event::MouseWheelScrolled (24 bytes)
├─╴struct SF::MouseWheelEvent (20 bytes)
│ └─╴struct SF::Event::MouseWheelMoved (20 bytes)
├─╴struct SF::KeyEvent (28 bytes)
│ ├─╴struct SF::Event::KeyReleased (28 bytes)
│ └─╴struct SF::Event::KeyPressed (28 bytes)
├─╴struct SF::TextEvent (12 bytes)
│ └─╴struct SF::Event::TextEntered (12 bytes)
├────╴struct SF::Event::GainedFocus (4 bytes)
├────╴struct SF::Event::LostFocus (4 bytes)
├─╴struct SF::SizeEvent (16 bytes)
│ └─╴struct SF::Event::Resized (16 bytes)
└────╴struct SF::Event::Closed (4 bytes)
Basically the 3rd level structs add absolutely nothing to its parent struct, they're just for distinguishing different events that have the same associated data. So naturally sometimes I want to cast to their common ancestor.
The 2nd level structs were originally in a union and the 3rd level structs were originally just enum values but I wanted to spice it up a little. Ended up changing struct to class everywhere.
I see. But you say "So naturally sometimes I want to cast to their common ancestor". In which cases do you need to explicitly do as SubStruct?
Well, here it's for compatibility with the union-based API.
Where Event#key would just return the key : KeyEvent union member, here it returns self as KeyEvent, which is meant to cause a runtime error if it isn't actually a KeyEvent
I just overrode this in the subsubclasses to return self without casting, and it prevents this bug (works even with structs).
Yeah, this example is too crazy to consider, but still... a compiler crash is a compiler crash :yum:
Oh no, nevermind, my fix breaks some other case.
@BlaXpirit I just wrote #2529 which explains the reason of this bug. I'm closing this as a duplicate of such issue. As a workaround (because I think we'll remove struct inheritance, or at least that's what I'd like to do), you can use a module and include it in other structs.
@BlaXpirit I understand the 👎 because of your struct hierarchy. However, are non-leaf structs concrete? (are they always abstract?) I mean, can a SF::SensorEvent exist (can you SF::SensorEvent.new?) or is it always going to be SF::Event::SensorChanged?
Because if so, the final decision of #2529 will allow you to model this hierarchy because abstract structs can be inherited.
@asterite Sounds good, thanks.