Skip to content

Object#crystal_type_id returns different value for virtual type in interpreter #14967

@HertzDevil

Description

@HertzDevil

In the following compiled code, upcasting a Bar to a Foo doesn't change the value of Object#crystal_type_id, because a type ID read is involved:

class Foo
end

class Bar < Foo
end

Foo.crystal_instance_type_id      # => 177
Bar.crystal_instance_type_id      # => 176
Foo.new.crystal_type_id           # => 177
Bar.new.crystal_type_id           # => 176
(Bar.new.as(Foo)).crystal_type_id # => 176
Bar.new.as(Foo).as(Int32*).value  # => 176

The same code produces a different result when interpreted:

Foo.crystal_instance_type_id      # => 188
Bar.crystal_instance_type_id      # => 189
Foo.new.crystal_type_id           # => 188
Bar.new.crystal_type_id           # => 189
(Bar.new.as(Foo)).crystal_type_id # => 190 # should be 189
Bar.new.as(Foo).as(Int32*).value  # => 189

The code responsible for this is:

if owner.is_a?(VirtualMetaclassType)
# For a virtual metaclass type, the value is already an int
# that's exactly the crystal_type_id, so there's nothing else to do.
if obj
request_obj_and_cast_if_needed(obj, owner)
else
put_self node: node
end
else
put_i32 type_id(owner), node: node
end

owner is a VirtualType, and 190 is the type ID for Foo+ instances. This however should never happen, because the point of crystal_type_id is to obtain the type ID corresponding to the run-time type.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions