Open-Source Wikis

/

Ruby

/

Core classes

ruby/ruby

Core classes

The implementations of Ruby's built-in types — String, Array, Hash, Integer, Float, Symbol, Proc, Method, Range, Regexp, Time, Struct, and so on. Most are split between a C file (memory layout, performance-critical operations) and an optional Ruby file (higher-level methods compiled into the binary).

Pages in this section

Page Covered classes
string-and-symbol.md String, Symbol, mutable vs frozen strings
array-and-hash.md Array, Hash, the st hash table, Set
numerics.md Integer, Float, Bignum, Rational, Complex
proc-and-method.md Proc, Lambda, Method, UnboundMethod, Binding

For IO and File see systems/io.md. For Regexp see systems/regexp.md. For Module/Class/object internals see systems/vm.md and reference/data-models.md.

How a core class is structured

Most core classes follow a consistent pattern:

  1. C struct in include/ruby/internal/core/: memory layout (RString, RArray, RHash, etc.).
  2. C source in the repo root (string.c, array.c, hash.c): allocation, mutation, performance-critical methods.
  3. Optional Ruby source at the same name (array.rb, hash.rb, etc.): higher-level methods that benefit from being expressed in Ruby. Compiled into the binary by tool/mk_builtin_loader.rb.
  4. Init function (Init_String, Init_Array, Init_Hash): registers methods with rb_define_method. Called from inits.c::rb_call_inits.

The Ruby-level files use a Primitive.foo syntax to call into C primitives. Example from array.rb:

class Array
  def each_index
    Primitive.attr! :inline_block
    return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)' unless block_given?
    i = 0
    while i < length
      yield i
      i += 1
    end
    self
  end
end

Primitive.cexpr! and Primitive.attr! are recognised by tool/mk_builtin_loader.rb and lowered to direct C calls or attribute flags.

Why split between C and Ruby?

Historically, every method was C. Over time, many were rewritten in Ruby because:

  • Ruby is easier to maintain than C.
  • The compiler (and JITs) can optimise Ruby method bodies just as well as inline C, given enough type information.
  • Errors and backtraces are cleaner when the body is Ruby.

The split is a judgement call per method. Anything that needs raw memory access (e.g., Array#sort, Hash#each) stays in C; control-flow-heavy methods that just orchestrate other methods (e.g., Array#each_index, Array#combination) move to Ruby.

Special-constant types

Several "core" types are not heap objects at all — they're encoded directly in the VALUE bits:

Type Encoding
Fixnum low bit set; the integer is in the upper 63 bits
Float (some platforms) low 2 bits = 0b10; mantissa in the upper bits
Symbol low bits = SPECIAL_CONST_TAG_SYM for short symbols, otherwise heap
nil Qnil (one-byte sentinel)
false Qfalse
true Qtrue

Method dispatch on these types still finds methods through the class hierarchy (Integer, Float, Symbol, NilClass, FalseClass, TrueClass); the VM has fast paths to avoid actually allocating an object.

See reference/data-models.md for the bit-level details.

Class hierarchy

BasicObject
└── Object
    ├── Numeric
    │   ├── Integer  (Fixnum, Bignum)
    │   ├── Float
    │   ├── Rational
    │   └── Complex
    ├── String         (also includes Symbol kind-of)
    ├── Symbol
    ├── Array
    ├── Hash
    ├── Range
    ├── Regexp
    ├── Proc
    ├── Method / UnboundMethod
    ├── Struct        (and Data, Set in newer versions)
    ├── Time
    ├── IO            (parent of File, Socket, ...)
    ├── Thread / Fiber / Ractor / Mutex / Queue / Monitor
    ├── Exception     (with StandardError, RuntimeError, ... subtree)
    └── Module
        └── Class

The full layout is built in inits.c::rb_call_inits and the per-class Init_* functions.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Core classes – Ruby wiki | Factory