NEWS for Ruby 3.1.0 ↑

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

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

Language changes ↑

  • The block argument can now be anonymous if the block will only be passed to another method. [Feature #11256]

    def foo(&)
      bar(&)
    end
    
  • Pin operator now takes an expression. [Feature #17411]

    Prime.each_cons(2).lazy.find_all{_1 in [n, ^(n + 2)]}.take(3).to_a
    #=> [[3, 5], [5, 7], [11, 13]]
    
  • Pin operator now supports instance, class, and global variables. [Feature #17724]

    @n = 5
    Prime.each_cons(2).lazy.find{_1 in [n, ^@n]}
    #=> [3, 5]
    
  • One-line pattern matching is no longer experimental.

  • Parentheses can be omitted in one-line pattern matching. [Feature #16182]

    [0, 1] => _, x
    {y: 2} => y:
    x #=> 1
    y #=> 2
    
  • Multiple assignment evaluation order has been made consistent with single assignment evaluation order. With single assignment, Ruby uses a left-to-right evaluation order. With this code:

    foo[0] = bar
    

    The following evaluation order is used:

    1. foo

    2. bar

    3. []= called on the result of foo

    In Ruby before 3.1.0, multiple assignment did not follow this evaluation order. With this code:

    foo[0], bar.baz = a, b
    

    Versions of Ruby before 3.1.0 would evaluate in the following order

    1. a

    2. b

    3. foo

    4. []= called on the result of foo

    5. bar

    6. baz= called on the result of bar

    Starting in Ruby 3.1.0, the evaluation order is now consistent with single assignment, with the left-hand side being evaluated before the right-hand side:

    1. foo

    2. bar

    3. a

    4. b

    5. []= called on the result of foo

    6. baz= called on the result of bar

    [Bug #4443]

  • Values in Hash literals and keyword arguments can be omitted. [Feature #14579]

    For example,

    • {x:, y:} is a syntax sugar of {x: x, y: y}.

    • foo(x:, y:) is a syntax sugar of foo(x: x, y: y).

    Constant names, local variable names, and method names are allowed as key names. Note that a reserved word is considered as a local variable or method name even if it's a pseudo variable name such as self.

  • Non main-Ractors can get instance variables (ivars) of classes/modules if ivars refer to shareable objects. [Feature #17592]

  • A command syntax is allowed in endless method definitions, i.e., you can now write def foo = puts "Hello". Note that private def foo = puts "Hello" does not parse. [Feature #17398]

Command line options ↑

  • --disable-gems is now explicitly declared as “just for debugging”. Never use it in any real-world codebase. [Feature #17684]

Core classes updates ↑

Note: We’re only listing outstanding class updates.

Stdlib updates ↑

  • The following default gem are updated.

    • RubyGems 3.3.3

    • base64 0.1.1

    • benchmark 0.2.0

    • bigdecimal 3.1.1

    • bundler 2.3.3

    • cgi 0.3.1

    • csv 3.2.2

    • date 3.2.2

    • did_you_mean 1.6.1

    • digest 3.1.0

    • drb 2.1.0

    • erb 2.2.3

    • error_highlight 0.3.0

    • etc 1.3.0

    • fcntl 1.0.1

    • fiddle 1.1.0

    • fileutils 1.6.0

    • find 0.1.1

    • io-console 0.5.10

    • io-wait 0.2.1

    • ipaddr 1.2.3

    • irb 1.4.1

    • json 2.6.1

    • logger 1.5.0

    • net-http 0.2.0

    • net-protocol 0.1.2

    • nkf 0.1.1

    • open-uri 0.2.0

    • openssl 3.0.0

    • optparse 0.2.0

    • ostruct 0.5.2

    • pathname 0.2.0

    • pp 0.3.0

    • prettyprint 0.1.1

    • psych 4.0.3

    • racc 1.6.0

    • rdoc 6.4.0

    • readline 0.0.3

    • readline-ext 0.1.4

    • reline 0.3.0

    • resolv 0.2.1

    • rinda 0.1.1

    • ruby2_keywords 0.0.5

    • securerandom 0.1.1

    • set 1.0.2

    • stringio 3.0.1

    • strscan 3.0.1

    • tempfile 0.1.2

    • time 0.2.0

    • timeout 0.2.0

    • tmpdir 0.1.2

    • un 0.2.0

    • uri 0.11.0

    • yaml 0.2.0

    • zlib 2.1.1

    • RubyGems 3.3.3

    • base64 0.1.1

    • benchmark 0.2.0

    • bigdecimal 3.1.1

    • bundler 2.3.3

    • cgi 0.3.1

    • csv 3.2.2

    • date 3.2.2

    • did_you_mean 1.6.1

    • digest 3.1.0

    • drb 2.1.0

    • erb 2.2.3

    • error_highlight 0.3.0

    • etc 1.3.0

    • fcntl 1.0.1

    • fiddle 1.1.0

    • fileutils 1.6.0

    • find 0.1.1

    • io-console 0.5.10

    • io-wait 0.2.1

    • ipaddr 1.2.3

    • irb 1.4.1

    • json 2.6.1

    • logger 1.5.0

    • net-http 0.2.0

    • net-protocol 0.1.2

    • nkf 0.1.1

    • open-uri 0.2.0

    • openssl 3.0.0

    • optparse 0.2.0

    • ostruct 0.5.2

    • pathname 0.2.0

    • pp 0.3.0

    • prettyprint 0.1.1

    • psych 4.0.3

    • racc 1.6.0

    • rdoc 6.4.0

    • readline 0.0.3

    • readline-ext 0.1.4

    • reline 0.3.0

    • resolv 0.2.1

    • rinda 0.1.1

    • ruby2_keywords 0.0.5

    • securerandom 0.1.1

    • set 1.0.2

    • stringio 3.0.1

    • strscan 3.0.1

    • tempfile 0.1.2

    • time 0.2.0

    • timeout 0.2.0

    • tmpdir 0.1.2

    • un 0.2.0

    • uri 0.11.0

    • yaml 0.2.0

    • zlib 2.1.1

  • The following bundled gems are updated.

    • minitest 5.15.0

    • power_assert 2.0.1

    • rake 13.0.6

    • test-unit 3.5.3

    • rexml 3.2.5

    • rbs 2.0.0

    • typeprof 0.21.1

    • minitest 5.15.0

    • power_assert 2.0.1

    • rake 13.0.6

    • test-unit 3.5.3

    • rexml 3.2.5

    • rbs 2.0.0

    • typeprof 0.21.1

  • The following default gems are now bundled gems.

    • net-ftp 0.1.3

    • net-imap 0.2.2

    • net-pop 0.1.1

    • net-smtp 0.3.1

    • matrix 0.4.2

    • prime 0.1.2

    • debug 1.4.0

    • net-ftp 0.1.3

    • net-imap 0.2.2

    • net-pop 0.1.1

    • net-smtp 0.3.1

    • matrix 0.4.2

    • prime 0.1.2

    • debug 1.4.0

  • The following gems has been removed from the Ruby standard library.

    • dbm

    • gdbm

    • tracer

    • dbm

    • gdbm

    • tracer

  • Coverage measurement now supports suspension. You can use Coverage.suspend to stop the measurement temporarily, and Coverage.resume to restart it. See [Feature #18176] in detail.

  • Random::Formatter is moved to random/formatter.rb, so that you can use Random#hex, Random#base64, and so on without SecureRandom. [Feature #18190]

Compatibility issues ↑

Note: Excluding feature bug fixes.

  • rb_io_wait_readable, rb_io_wait_writable and rb_wait_for_single_fd are deprecated in favour of rb_io_maybe_wait_readable, rb_io_maybe_wait_writable and rb_io_maybe_wait respectively. rb_thread_wait_fd and rb_thread_fd_writable are deprecated. [Bug #18003]

Stdlib compatibility issues ↑

  • ERB#initialize warns safe_level and later arguments even without -w. [Feature #14256]

  • lib/debug.rb is replaced with debug.gem

  • Kernel#pp in lib/pp.rb uses the width of IO#winsize by default. This means that the output width is automatically changed depending on your terminal size. [Feature #12913]

  • Psych 4.0 changes Psych.load as safe_load by the default. You may need to use Psych 3.3.2 for migrating to this behavior. [Bug #17866]

C API updates ↑

  • Documented. [GH-4815]

  • rb_gc_force_recycle is deprecated and has been changed to a no-op. [Feature #18290]

Implementation improvements ↑

  • Inline cache mechanism is introduced for reading class variables. [Feature #17763]

  • instance_eval and instance_exec now only allocate a singleton class when required, avoiding extra objects and improving performance. [GH-5146]

  • The performance of Struct accessors is improved. [GH-5131]

  • mandatory_only? builtin special form to improve performance on builtin methods. [GH-5112]

  • Experimental feature Variable Width Allocation in the garbage collector. This feature is turned off by default and can be enabled by compiling Ruby with flag USE_RVARGC=1 set. [Feature #18045] [Feature #18239]

JIT ↑

  • Rename Ruby 3.0’s --jit to --mjit, and alias --jit to --yjit on non-Windows x86-64 platforms and to --mjit on others.

MJIT ↑

  • The default --mjit-max-cache is changed from 100 to 10000.

  • JIT-ed code is no longer cancelled when a TracePoint for class events is enabled.

  • The JIT compiler no longer skips compilation of methods longer than 1000 instructions.

  • --mjit-verbose and --mjit-warning output “JIT cancel” when JIT-ed code is disabled because TracePoint or GC.compact is used.

YJIT: New experimental in-process JIT compiler ↑

New JIT compiler available as an experimental feature. [Feature #18229]

See this blog post introducing the project.

  • Disabled by default, use --yjit command-line option to enable YJIT.

  • Performance improvements on benchmarks based on real-world software, up to 22% on railsbench, 39% on liquid-render.

  • Fast warm-up times.

  • Limited to Unix-like x86-64 platforms for now.

Static analysis ↑

RBS ↑

  • Generics type parameters can be bounded (PR).

    # `T` must be compatible with the `_Output` interface.
    # `PrettyPrint[String]` is ok, but `PrettyPrint[Integer]` is a type error.
    class PrettyPrint[T < _Output]
      interface _Output
        def <<: (String) -> void
      end
    
      attr_reader output: T
    
      def initialize: (T output) -> void
    end
  • Type aliases can be generic. (PR)

    # Defines a generic type `list`.
    type list[T] = [ T, list[T] ]
                 | nil
    
    type str_list = list[String]
    type int_list = list[Integer]
  • rbs collection has been introduced to manage gems’ RBSs.

  • Many signatures for built-in and standard libraries have been added/updated.

  • It includes many bug fixes and performance improvements too.

See the CHANGELOG.md for more information.

TypeProf ↑

Debugger ↑

  • A new debugger debug.gem is bundled. debug.gem is a fast debugger implementation, and it provides many features like remote debugging, colorful REPL, IDE (VSCode) integration, and more. It replaces lib/debug.rb standard library.

  • rdbg command is also installed into bin/ directory to start and control debugging execution.

error_highlight ↑

A built-in gem called error_highlight has been introduced. It shows fine-grained error locations in the backtrace.

Example: title = json[:article][:title]

If json is nil, it shows:

$ ruby test.rb
test.rb:2:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)

title = json[:article][:title]
            ^^^^^^^^^^

If json[:article] returns nil, it shows:

$ ruby test.rb
test.rb:2:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)

title = json[:article][:title]
                      ^^^^^^^^

This feature is enabled by default. You can disable it by using a command-line option --disable-error_highlight. See the repository in detail.

IRB Autocomplete and Document Display ↑

The IRB now has an autocomplete feature, where you can just type in the code, and the completion candidates dialog will appear. You can use Tab and Shift+Tab to move up and down.

If documents are installed when you select a completion candidate, the documentation dialog will appear next to the completion candidates dialog, showing part of the content. You can read the full document by pressing Alt+d.

Miscellaneous changes ↑

  • lib/objspace/trace.rb is added, which is a tool for tracing the object allocation. Just by requiring this file, tracing is started immediately. Just by Kernel#p, you can investigate where an object was created. Note that just requiring this file brings a large performance overhead. This is only for debugging purposes. Do not use this in production. [Feature #17762]

  • Now exceptions raised in finalizers will be printed to STDERR, unless $VERBOSE is nil. [Feature #17798]

  • ruby -run -e httpd displays URLs to access. [Feature #17847]

  • Add ruby -run -e colorize to colorize Ruby code using IRB::Color.colorize_code.