Skip to content

Ruby 3.4 support #8395

@headius

Description

@headius

NEWS for Ruby 3.4.0

This document is a list of user-visible feature changes
since the 3.3.0 release, except for bug fixes.

Note that each entry is kept to a minimum, see links for details.

Language changes

  • String literals in files without a frozen_string_literal comment now emit a deprecation warning
    when they are mutated.
    These warnings can be enabled with -W:deprecated or by setting Warning[:deprecated] = true.
    To disable this change, you can run Ruby with the --disable-frozen-string-literal
    command line argument. [Feature #20205]
  • it is added to reference a block parameter. [Feature #18980]
  • Keyword splatting nil when calling methods is now supported.
    **nil is treated similarly to **{}, passing no keywords,
    and not calling any conversion methods. [Bug #20064]
  • Block passing is no longer allowed in index assignment
    (e.g. a[0, &b] = 1). [Bug #19918]
  • Keyword arguments are no longer allowed in index assignment
    (e.g. a[0, kw: 1] = 2). [Bug #20218]
  • The toplevel name ::Ruby is reserved now, and the definition will be warned
    when Warning[:deprecated]. [Feature #20884]

Core classes updates

Note: We're only listing outstanding class updates.

  • Array

  • Exception

    • Exception#set_backtrace now accepts arrays of Thread::Backtrace::Location. Kernel#raise, Thread#raise and Fiber#raise also accept this new format. [Feature #13557]
  • Fiber::Scheduler

    • An optional Fiber::Scheduler#blocking_operation_wait hook allows blocking operations to be moved out of the event loop in order to reduce latency and improve multi-core processor utilization. [Feature #20876]
  • GC

    • GC.config added to allow setting configuration variables on the Garbage Collector. [Feature #20443]

    • GC configuration parameter rgengc_allow_full_mark introduced. When false GC will only mark young objects. Default is true. [Feature #20443]

  • Hash

    • Hash.new now accepts an optional capacity: argument, to preallocate the hash with a given capacity. This can improve performance when building large hashes incrementally by saving on reallocation and rehashing of keys. [Feature #19236]
  • IO::Buffer

    • IO::Buffer#copy can release the GVL, allowing other threads to run while copying data. [Feature #20902]
  • Integer

    • Integer#** used to return Float::INFINITY when the return value is large, but now returns an Integer. If the return value is extremely large, it raises an exception. [Feature #20811]
  • MatchData

    • MatchData#bytebegin and MatchData#byteend have been added. [Feature #20576]
  • Object

    • Object#singleton_method now returns methods in modules prepended to or included in the receiver's singleton class. [Bug #20620]

      o = Object.new
      o.extend(Module.new{def a = 1})
      o.singleton_method(:a).call #=> 1
  • Ractor

    • require in Ractor is allowed. The requiring process will be run on the main Ractor.
      Ractor._require(feature) is added to run requiring process on the main Ractor.
      [Feature #20627]

    • Ractor.main? is added. [Feature #20627]

    • Ractor.[] and Ractor.[]= are added to access the ractor local storage of the current Ractor. [Feature #20715]

    • Ractor.store_if_absent(key){ init } is added to initialize ractor local variables in thread-safety. [Feature #20875]

  • Range

    • Range#size now raises TypeError if the range is not iterable. [Misc #18984]

    • Range#step now consistently has a semantics of iterating by using + operator for all types, not only numerics. [Feature #18368]

      (Time.utc(2022, 2, 24)..).step(24*60*60).take(3)
      #=> [2022-02-24 00:00:00 UTC, 2022-02-25 00:00:00 UTC, 2022-02-26 00:00:00 UTC]
  • RubyVM::AbstractSyntaxTree

    • Add RubyVM::AbstractSyntaxTree::Node#locations method which returns location objects associated with the AST node. [Feature #20624]
    • Add RubyVM::AbstractSyntaxTree::Location class which holds location information. [Feature #20624]
  • String

    • String#append_as_bytes was added to more easily and efficiently work with binary buffers and protocols. It directly concatenate the arguments into the string without any encoding validation or conversion. [Feature #20594]
  • Symbol

    • The string returned by Symbol#to_s now emits a deprecation warning when mutated, and will be frozen in a future version of Ruby. These warnings can be enabled with -W:deprecated or by setting Warning[:deprecated] = true. [Feature #20350]
  • Time

    • On Windows, now Time#zone encodes the system timezone name in UTF-8 instead of the active code page, if it contains non-ASCII characters. [Bug #20929]

    • Time#xmlschema, and its Time#iso8601 alias have been moved into the core Time class while previously it was an extension provided by the time gem. [Feature #20707]

  • Warning

    • Add Warning.categories method which returns a list of possible warning categories. [Feature #20293]

Stdlib updates

  • RubyGems

    • Add --attestation option to gem push. It enabled to store signature of build artifact to sigstore.dev.
  • Bundler

    • Add a lockfile_checksums configuration to include checksums in fresh lockfiles.
    • Add bundle lock --add-checksums to add checksums to an existing lockfile.
  • JSON

    • Performance improvements JSON.parse about 1.5 times faster than json-2.7.x.
  • Tempfile

    • The keyword argument anonymous: true is implemented for Tempfile.create.
      Tempfile.create(anonymous: true) removes the created temporary file immediately.
      So applications don't need to remove the file.
      [Feature #20497]
  • win32/sspi.rb

  • Socket

    • Socket::ResolutionError and Socket::ResolutionError#error_code was added.
      [Feature #20018]
  • IRB

    • Interactive method completion is now improved with type information by default.
      [Feature #20778]

The following default gems are updated.

The following bundled gem is added.

The following bundled gems are updated.

The following bundled gems are promoted from default gems.

Compatibility issues

  • Error messages and backtrace displays have been changed.

    • Use a single quote instead of a backtick as an opening quote. [Feature #16495]

    • Display a class name before a method name in backtrace #8660

    • Extra rescue/ensure frames are no longer available on the backtrace. [Feature #20275]

    • Kernel#caller, Thread::Backtrace::Location’s methods, etc. are also changed accordingly.

      Old:

      test.rb:1:in `foo': undefined method `time' for an instance of Integer
              from test.rb:2:in `<main>'
      

      New:

      test.rb:1:in 'Object#foo': undefined method 'time' for an instance of Integer
              from test.rb:2:in '<main>'
      
  • Hash#inspect rendering have been changed. [Bug #20433]

    • Symbol keys are displayed using the modern symbol key syntax: "{user: 1}"
    • Other keys now have spaces around =>: '{"user" => 1}', while previously they didn't: '{"user"=>1}'
  • Kernel#Float() now accepts a decimal string with decimal part omitted. [Feature #20705]

    Float("1.")    #=> 1.0 (previously, an ArgumentError was raised)
    Float("1.E-1") #=> 0.1 (previously, an ArgumentError was raised)
  • String#to_f now accepts a decimal string with decimal part omitted. [Feature #20705]
    Note that the result changes when an exponent is specified.

    "1.".to_f    #=> 1.0
    "1.E-1".to_f #=> 0.1 (previously, 1.0 was returned)
  • Refinement#refined_class has been removed. [Feature #19714]

Stdlib compatibility issues

  • DidYouMean

    • DidYouMean::SPELL_CHECKERS[]= and DidYouMean::SPELL_CHECKERS.merge! are removed.
  • Net::HTTP

    • Removed the following deprecated constants:

      • Net::HTTP::ProxyMod
      • Net::NetPrivate::HTTPRequest
      • Net::HTTPInformationCode
      • Net::HTTPSuccessCode
      • Net::HTTPRedirectionCode
      • Net::HTTPRetriableCode
      • Net::HTTPClientErrorCode
      • Net::HTTPFatalErrorCode
      • Net::HTTPServerErrorCode
      • Net::HTTPResponseReceiver
      • Net::HTTPResponceReceiver

      These constants were deprecated from 2012.

  • Timeout

    • Reject negative values for Timeout.timeout. [Bug #20795]
  • URI

    • Switched default parser to RFC 3986 compliant from RFC 2396 compliant.
      [Bug #19266]

Implementation improvements

  • The default parser is now Prism.
    To use the conventional parser, use the command-line argument --parser=parse.y.
    [Feature #20564]

  • Happy Eyeballs version 2 (RFC8305), an algorithm that ensures faster and more reliable connections
    by attempting IPv6 and IPv4 concurrently, is used in Socket.tcp and TCPSocket.new.
    To disable it globally, set the environment variable RUBY_TCP_NO_FAST_FALLBACK=1 or
    call Socket.tcp_fast_fallback=false.
    Or to disable it on a per-method basis, use the keyword argument fast_fallback: false.
    [Feature #20108] [Feature #20782]

  • Alternative garbage collector (GC) implementations can be loaded dynamically
    through the modular garbage collector feature. To enable this feature,
    configure Ruby with --with-modular-gc at build time. GC libraries can be
    loaded at runtime using the environment variable RUBY_GC_LIBRARY.
    [Feature #20351]

  • Ruby's built-in garbage collector has been split into a separate file at
    gc/default/default.c and interacts with Ruby using an API defined in
    gc/gc_impl.h. The built-in garbage collector can now also be built as a
    library using make modular-gc MODULAR_GC=default and enabled using the
    environment variable RUBY_GC_LIBRARY=default. [Feature #20470]

  • An experimental GC library is provided based on MMTk.
    This GC library can be built using make modular-gc MODULAR_GC=mmtk and
    enabled using the environment variable RUBY_GC_LIBRARY=mmtk. This requires
    the Rust toolchain on the build machine. [Feature #20860]

YJIT

New features

  • Command-line options
    • --yjit-mem-size introduces a unified memory limit (default 128MiB) to track total YJIT memory usage,
      providing a more intuitive alternative to the old --yjit-exec-mem-size option.
    • --yjit-trace-exits=COUNTER allows tracing of counted exits and fallbacks.
    • --yjit-perf=codegen allows profiling of JIT code based on YJIT's codegen functions.
    • --yjit-log enables a compilation log to track what gets compiled.
  • Ruby API
    • RubyVM::YJIT.enable(log: true) also enables a compilation log.
    • RubyVM::YJIT.log provides access to the tail of the compilation log at run-time.
  • YJIT stats
    • RubyVM::YJIT.runtime_stats now always provides additional statistics on
      invalidation, inlining, and metadata encoding.
    • RubyVM::YJIT.runtime_stats[:iseq_calls] is added to profile non-inlined Ruby method calls.
    • RubyVM::YJIT.runtime_stats[:cfunc_calls] is truncated to the top 20 entries for better performance.

New optimizations

  • Compressed context reduces memory needed to store YJIT metadata
  • Allocate registers for local variables and Ruby method arguments
  • When YJIT is enabled, use more Core primitives written in Ruby:
    • Array#each, Array#select, Array#map rewritten in Ruby for better performance [Feature #20182].
  • Ability to inline small/trivial methods such as:
    • Empty methods
    • Methods returning a constant
    • Methods returning self
    • Methods directly returning an argument
  • Specialized codegen for many more runtime methods
  • Optimize String#getbyte, String#setbyte and other string methods
  • Optimize bitwise operations to speed up low-level bit/byte manipulation
  • Support shareable constants in multi-ractor mode
  • Various other incremental optimizations

Miscellaneous changes

  • Passing a block to a method which doesn't use the passed block will show
    a warning on verbose mode (-w).
    In connection with this, a new strict_unused_block warning category was introduced.
    Turn them on with -W:strict_unused_block or Warning[:strict_unused_block] = true.
    [Feature #15554]

  • Redefining some core methods that are specially optimized by the interpreter
    and JIT like String#freeze or Integer#+ now emits a performance class
    warning (-W:performance or Warning[:performance] = true).
    [Feature #20429]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions