Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support generic types in crystal tool hierarchy #13715

Conversation

HertzDevil
Copy link
Contributor

Right now, the hierarchy tool does not support generic types, in that it simply prints those types' instance variables themselves again instead of their types and sizes:

$ bin/crystal tool hierarchy src/prelude.cr -e "^(Array|Slice)$"
- class Object (4 bytes)
  |
  +- class Reference (4 bytes)
  |  |
  |  +- class Array(T)
  |         @size             : @size
  |         @capacity         : @capacity
  |         @offset_to_buffer : @offset_to_buffer
  |         @buffer           : @buffer
  |
  +- struct Value (0 bytes)
     |
     +- struct Struct (0 bytes)
        |
        +- struct Slice(T)
               @size      : @size
               @read_only : @read_only
               @pointer   : @pointer

This PR adds support for those members by ensuring that the byte sizes are queried only when they are independent of any unbound type parameters, most notably instances of Pointer and Proc:

class Array(T) (24 bytes)
    @size             : Int32      (4 bytes)
    @capacity         : Int32      (4 bytes)
    @offset_to_buffer : Int32      (4 bytes)
    @buffer           : Pointer(T) (8 bytes)

struct Slice(T) (16 bytes)
    @size      : Int32      (4 bytes)
    @read_only : Bool       (1 bytes)
    @pointer   : Pointer(T) (8 bytes)

In this case, all of Array and Slice's members have constant sizes, so their total sizes are also shown.

When used as an instance variable, Array has a fixed size regardless of its members, because Array is a reference:

class Indexable::CombinationIterator(A, T) (64 bytes)
    @size    : Int32            (4 bytes)
    @n       : Int32            (4 bytes)
    @copy    : Array(T)         (8 bytes)
    @pool    : Array(T)         (8 bytes)
    @indices : Array(Int32)     (8 bytes)
    @stop    : Bool             (1 bytes)
    @i       : Int32            (4 bytes)
    @first   : Bool             (1 bytes)
    @reuse   : (Array(T) | Nil) (8 bytes)

For structs, an example of a constant-size generic type being used generically is Set:

struct Set(T) (8 bytes)
    @hash : Hash(T, Nil) (8 bytes)

struct Iterator::UniqIterator(I, T, U)
    @iterator : I
    @func     : Proc(T, U) (16 bytes)
    @set      : Set(U)     ( 8 bytes)

Here Iterator::UniqIterator does not have a constant size because @iterator's size can change depending on I.

Copy link
Member

@beta-ziliani beta-ziliani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@beta-ziliani beta-ziliani added this to the 1.10.0 milestone Jul 31, 2023
@beta-ziliani beta-ziliani merged commit c592ded into crystal-lang:master Aug 4, 2023
52 of 53 checks passed
@HertzDevil HertzDevil deleted the feature/tool-hierarchy-generic-types branch August 24, 2023 12:23
Blacksmoke16 pushed a commit to Blacksmoke16/crystal that referenced this pull request Dec 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants