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: - 
foo
- 
bar
- 
[]=called on the result offoo
 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 - 
a
- 
b
- 
foo
- 
[]=called on the result offoo
- 
bar
- 
baz=called on the result ofbar
 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: - 
foo
- 
bar
- 
a
- 
b
- 
[]=called on the result offoo
- 
baz=called on the result ofbar
 
- 
- 
Values in Hashliterals 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 offoo(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 thatprivate def foo = puts "Hello"does not parse. [Feature #17398]
Command line options¶ ↑
- 
--disable-gemsis 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.
- 
- 
Array#intersect?is added. [Feature #15198]
 
- 
- 
- 
Class#subclasses, which returns an array of classes directly inheriting from the receiver, not including singleton classes. [Feature #18273]class A; end class B < A; end class C < B; end class D < A; end A.subclasses #=> [D, B] B.subclasses #=> [C] C.subclasses #=> [] 
 
- 
- 
- 
Enumerable#compactis added. [Feature #17312]
- 
Enumerable#tallynow accepts an optional hash to count. [Feature #17744]
- 
Enumerable#each_consand each_slice to return a receiver. [GH-1509][1, 2, 3].each_cons(2){} # 3.0 => nil # 3.1 => [1, 2, 3] [1, 2, 3].each_slice(2){} # 3.0 => nil # 3.1 => [1, 2, 3] 
 
- 
- 
- 
Enumerator::Lazy#compactis added. [Feature #17312]
 
- 
- 
- 
File.dirnamenow accepts an optional argument for the level to strip path components. [Feature #12194]
 
- 
- 
- 
"GC.measure_total_time = true" enables the measurement of GC. Measurement can introduce overhead. It is enabled by default.GC.measure_total_timereturns the current setting.GC.stat[:time]orGC.stat(:time) returns measured time in milli-seconds. [[Feature #10917]]
- 
GC.total_timereturns measured time in nano-seconds. [[Feature #10917]]
 
- 
- 
- 
Integer.try_convertis added. [Feature #15211]
 
- 
- 
- 
Kernel#loadnow accepts a module as the second argument, and will load the file using the given module as the top-level module. [Feature #6210]
 
- 
- 
- 
Marshal.loadnow accepts afreeze: trueoption. All returned objects are frozen except forClassandModuleinstances. Strings are deduplicated. [Feature #18148]
 
- 
- 
- 
MatchData#matchis added [Feature #18172]
- 
MatchData#match_lengthis added [Feature #18172]
 
- 
- 
- 
Method#public?, Method#private?, Method#protected?, UnboundMethod#public?, UnboundMethod#private?, UnboundMethod#protected? have been added. [Feature #11689] 
 
- 
- 
- 
Module#prependnow modifies the ancestor chain if the receiver already includes the argument.Module#prependstill does not modify the ancestor chain if the receiver has already prepended the argument. [Bug #17423]
- 
Module#private, public, protected, and module_function will now return their arguments. If a single argument is given, it is returned. If no arguments are given, nil is returned. If multiple arguments are given, they are returned as an array. [Feature #12495] 
 
- 
- 
- 
Process._forkis added. This is a core method for fork(2). Do not call this method directly; it is called by existing fork methods:Kernel.#fork,Process.fork, andIO.popen(“-”). Application monitoring libraries can overwrite this method to hook fork events. [Feature #17795]
 
- 
- 
- 
Passing only keyword arguments to Struct#initialize is warned. You need to use a Hashliteral to set aHashto a first member. [Feature #16806]
- 
StructClass#keyword_init? is added [Feature #18008] 
 
- 
- 
- 
Update Unicode version to 13.0.0 [Feature #17750] and Emoji version to 13.0 [Feature #18029] 
- 
String#unpackandString#unpack1now accept anoffset:keyword argument to start the unpacking after an arbitrary number of bytes have been skipped. Ifoffsetis outside of the string boundsArgumentErroris raised. [Feature #18254]
 
- 
- 
- 
Thread#native_thread_idis added. [Feature #17853]
 
- 
- 
- 
Thread::Backtrace.limit, which returns the value to limit backtrace length set by--backtrace-limitcommand line option, is added. [Feature #17479]
 
- 
- 
- 
Thread::Queue.newnow accepts anEnumerableof initial values. [Feature #17327]
 
- 
- 
- 
Time.newnow accepts optionalin:keyword argument for the timezone, as well asTime.atandTime.now, so that is now you can omit minor arguments toTime.new. [Feature #17485]Time.new(2021, 12, 25, in: "+07:00") #=> 2021-12-25 00:00:00 +0700 At the same time, time component strings are converted to integers more strictly now. Time.new(2021, 12, 25, "+07:30") #=> invalid value for Integer(): "+07:30" (ArgumentError) Ruby 3.0 or earlier returned probably unexpected result 2021-12-25 07:00:00, not2021-12-25 07:30:00nor2021-12-25 00:00:00 +07:30.
- 
Time#strftimesupports RFC 3339 UTC for unknown offset local time,-0000, as%-z. [Feature #17544]
 
- 
- 
- 
TracePoint.allow_reentryis added to allow reenter whileTracePointcallback. [Feature #15912]
 
- 
- 
$LOAD_PATH - 
$LOAD_PATH.resolve_feature_path does not raise. [Feature #16043] 
 
- 
- 
FiberScheduler- 
Add support for Addrinfo.getaddrinfousingaddress_resolvehook. [Feature #17370]
- 
Introduce non-blocking Timeout.timeoutusingtimeout_afterhook. [Feature #17470]
- 
Introduce new scheduler hooks io_readandio_writealong with a low levelIO::Bufferfor zero-copy read/write. [Feature #18020]
- 
IOhooksio_wait,io_read,io_write, receive the originalIOobject where possible. [Bug #18003]
- 
Make Monitorfiber-safe. [Bug #17827]
- 
Replace copy coroutine with pthread implementation. [Feature #18015] 
 
- 
- 
- 
New class which represents a module created by Module#refine. includeandprependare deprecated, andimport_methodsis added instead. [Bug #17429]
 
- 
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 
 
- 
- 
Coveragemeasurement now supports suspension. You can useCoverage.suspendto stop the measurement temporarily, andCoverage.resumeto restart it. See [Feature #18176] in detail.
- 
Random::Formatteris moved to random/formatter.rb, so that you can useRandom#hex,Random#base64, and so on withoutSecureRandom. [Feature #18190]
Compatibility issues¶ ↑
Note: Excluding feature bug fixes.
- 
rb_io_wait_readable,rb_io_wait_writableandrb_wait_for_single_fdare deprecated in favour ofrb_io_maybe_wait_readable,rb_io_maybe_wait_writableandrb_io_maybe_waitrespectively.rb_thread_wait_fdandrb_thread_fd_writableare deprecated. [Bug #18003]
Stdlib compatibility issues¶ ↑
- 
ERB#initializewarnssafe_leveland later arguments even without -w. [Feature #14256]
- 
lib/debug.rbis replaced withdebug.gem
- 
Kernel#ppinlib/pp.rbuses the width ofIO#winsizeby default. This means that the output width is automatically changed depending on your terminal size. [Feature #12913]
- 
Psych4.0 changesPsych.loadassafe_loadby the default. You may need to usePsych3.3.2 for migrating to this behavior. [Bug #17866]
C API updates¶ ↑
- 
Documented. [GH-4815] 
- 
rb_gc_force_recycleis 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_evalandinstance_execnow only allocate a singleton class when required, avoiding extra objects and improving performance. [GH-5146]
- 
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=1set. [Feature #18045] [Feature #18239]
JIT¶ ↑
- 
Rename Ruby 3.0’s --jitto--mjit, and alias--jitto--yjiton non-Windows x86-64 platforms and to--mjiton others.
MJIT¶ ↑
- 
The default --mjit-max-cacheis changed from 100 to 10000.
- 
JIT-ed code is no longer cancelled when a TracePointfor class events is enabled.
- 
The JIT compiler no longer skips compilation of methods longer than 1000 instructions. 
- 
--mjit-verboseand--mjit-warningoutput “JIT cancel” when JIT-ed code is disabled becauseTracePointorGC.compactis 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 --yjitcommand-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¶ ↑
- 
Experimental IDE support has been implemented. 
- 
Many bug fixes and performance improvements since Ruby 3.0.0. 
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.rbstandard library.
- 
rdbgcommand is also installed intobin/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$VERBOSEisnil. [Feature #17798]
- 
ruby -run -e httpddisplays URLs to access. [Feature #17847]
- 
Add ruby -run -e colorizeto colorize Ruby code usingIRB::Color.colorize_code.