From 4cc465cdd7fc3e1e1a755c9425e1409d2a2bcb09 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Sun, 26 Jun 2022 07:18:00 -0300 Subject: [PATCH] Interpter: fix cast from virtual metaclass to union --- spec/compiler/interpreter/casts_spec.cr | 17 +++++++++++++++++ src/compiler/crystal/interpreter/cast.cr | 10 ++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/spec/compiler/interpreter/casts_spec.cr b/spec/compiler/interpreter/casts_spec.cr index 5be29e46821b..2c7011071241 100644 --- a/spec/compiler/interpreter/casts_spec.cr +++ b/spec/compiler/interpreter/casts_spec.cr @@ -273,5 +273,22 @@ describe Crystal::Repl::Interpreter do end CODE end + + it "puts virtual metaclass into union (#12162)" do + interpret(<<-CODE, prelude: "prelude").should eq(%("ActionA")) + class Action + end + + class ActionA < Action + end + + class ActionB < Action + end + + x = ActionA || ActionB + y = x || Nil + y.to_s + CODE + end end end diff --git a/src/compiler/crystal/interpreter/cast.cr b/src/compiler/crystal/interpreter/cast.cr index 13fefad64ec4..07b97d5a722c 100644 --- a/src/compiler/crystal/interpreter/cast.cr +++ b/src/compiler/crystal/interpreter/cast.cr @@ -63,11 +63,17 @@ class Crystal::Repl::Compiler end private def upcast_distinct(node : ASTNode, from : VirtualMetaclassType, to : MixedUnionType) - # Copy the type id + # We have a type ID (8 bytes) in the stack. + # We need to put that into a union whose: + # - tag will be the type ID (8 bytes) + # - value will be the type ID (8 bytes) followed by zeros to fill up the union size + + # We already have 8 bytes in the stack. That's the tag. + # Now we put the type ID again for the value. So far we have 16 bytes in total. dup 8, node: nil # Then fill out the rest of the union - remaining = aligned_sizeof_type(to) - 8 + remaining = aligned_sizeof_type(to) - 16 push_zeros remaining, node: nil if remaining > 0 end