17 KiB
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 be 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.
-
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, 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 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 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 definition, 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-gems
is now explicitly declared as "just for debugging". Never use it in any real-world code base. [Feature #17684]
Core classes updates
Outstanding ones only.
-
Array
- Array#intersect? is added. [Feature #15198]
-
Class
-
Class#descendants, which returns an array of classes directly or indirectly inheriting from the receiver, not including the receiver or singleton classes. [Feature #14394]
class A; end class B < A; end class C < B; end A.descendants #=> [B, C] B.descendants #=> [C] C.descendants #=> []
-
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
-
Enumerable#compact is added. [Feature #17312]
-
Enumerable#tally now accepts an optional hash to count. [Feature #17744]
-
Enumerable#each_cons and 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
- Enumerator::Lazy#compact is added. [Feature #17312]
-
File
- File.dirname now accepts an optional argument for the level to strip path components. [Feature #12194]
-
GC
-
"GC.measure_total_time = true" enables the measurement of GC. Measurement can introduce overhead. It is enabled by default. GC.measure_total_time returns the current setting. GC.stat[:time] or GC.stat(:time) returns measured time in milli-soconds.
-
GC.total_time returns measured time in nano-seconds.
-
-
Integer
- Integer.try_convert is added. [Feature #15211]
-
Kernel
- Kernel#load now accepts a module as the second argument, and will load the file using the given module as the top level module. [Feature #6210]
-
MatchData
-
MatchData#match is added [Feature #18172]
-
MatchData#match_length is added [Feature #18172]
-
-
Method/UnboundMethod
- Method#public?, Method#private?, Method#protected?, UnboundMethod#public?, UnboundMethod#private?, UnboundMethod#protected? have been added. [Feature #11689]
-
Module
-
Module#prepend now modifies the ancestor chain if the receiver already includes the argument. Module#prepend still 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
- Process._fork is 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, and IO.popen("-"). Application monitoring libraries can overwride this method to hook fork event. [Feature #17795]
-
Struct
-
Passing only keyword arguments to Struct#initialize is warned. You need to use a Hash literal to set a Hash to a first member. [Feature #16806]
-
StructClass#keyword_init? is added [Feature #18008]
-
-
String
- Update Unicode version to 13.0.0 [Feature #17750] and Emoji version to 13.0 [Feature #18029]
-
Queue
- Queue#initialize now accepts an Enumerable of initial values. [Feature #17327]
-
Thread
- Thread#native_thread_id is added. [Feature #17853]
-
Thread::Backtrace
- Thread::Backtrace.limit, which returns the value to limit backtrace
length set by
--backtrace-limit
command line option, is added. [Feature #17479]
- Thread::Backtrace.limit, which returns the value to limit backtrace
length set by
-
Time
-
Time.new now accepts optional
in:
keyword argument for the timezone, as well asTime.at
andTime.now
, so that is now you can omit minor arguments toTime.new
. [Feature #17485] -
Time#strftime supports RFC 3339 UTC for unknown offset local time,
-0000
, as%-z
. [Feature #17544]
-
-
TracePoint
- TracePoint.allow_reenter is added to allow reenter while TracePoint callback. Feature #15912
-
$LOAD_PATH
- $LOAD_PATH.resolve_feature_path does not raise. [Feature #16043]
-
Fiber Scheduler
-
Add support for
Addrinfo.getaddrinfo
usingaddress_resolve
hook. [Feature #17370] -
Introduce non-blocking
Timeout.timeout
usingtimeout_after
hook. [Feature #17470] -
Introduce new scheduler hooks
io_read
andio_write
along with a low levelIO::Buffer
for zero-copy read/write. [Feature #18020] -
IO hooks
io_wait
,io_read
,io_write
, receive the original IO object where possible. [Bug #18003] -
Make
Monitor
fiber-safe. [Bug #17827] -
Replace copy coroutine with pthread implementation. [Feature #18015]
-
-
Refinement
- New class which represents a module created by Module#refine.
include
andprepend
are deprecated, andimport_methods
is added instead. [Bug #17429]
- New class which represents a module created by Module#refine.
Stdlib updates
-
The following default gem are updated.
- RubyGems
- Bundler
- RDoc 6.3.2
- ReLine
- JSON 2.6.1
- Psych 4.0.2
- FileUtils 1.6.0
- Fiddle 1.1.0
- StringIO 3.0.1
- IO::Console 0.5.9
- IO::Wait 0.2.1
- CSV 3.2.1
- Etc 1.3.0
- Date 3.2.2
- Zlib 2.1.1
- StringScanner 3.0.1
- IpAddr 1.2.3
- Logger 1.4.4
- OStruct 0.5.2
- Irb
- Racc 1.6.0
- Delegate 0.2.0
- Benchmark 0.2.0
- CGI 0.3.1
- Readline(C-ext) 0.1.3
- Timeout 0.2.0
- YAML 0.2.0
- URI 0.11.0
- OpenSSL
- DidYouMean
- Weakref 0.1.1
- Tempfile 0.1.2
- TmpDir 0.1.2
- English 0.7.1
- Net::Protocol 0.1.2
- Net::Http 0.2.0
- BigDecimal
- OptionParser 0.2.0
- Set 1.0.2
- Find 0.1.1
- Rinda 0.1.1
- Erb 2.2.3
- NKF 0.1.1
- Base64 0.1.1
- OpenUri 0.2.0
- SecureRandom 0.1.1
- Resolv 0.2.1
- Resolv::Replace 0.1.0
- Time 0.2.0
- PP 0.2.1
- Prettyprint 0.1.1
- Drb 2.1.0
- Pathname 0.2.0
- Digest 3.1.0.pre3
- Un 0.2.0
-
The following bundled gems are updated.
- minitest 5.14.4
- power_assert 2.0.1
- rake 13.0.6
- test-unit 3.5.2
- rbs 1.8.0
- typeprof 0.20.4
-
The following default gems are now bundled gems.
- net-ftp
- net-imap
- net-pop
- net-smtp
- matrix
- prime
-
Coverage measurement nohw supports suspension. You can use
Coverage.suspend
to stop the measurement temporarily, andCoverage.resume
to restart it. See [Feature #18176] in detail.
Compatibility issues
Excluding feature bug fixes.
rb_io_wait_readable
,rb_io_wait_writable
andrb_wait_for_single_fd
are deprecated in favour ofrb_io_maybe_wait_readable
,rb_io_maybe_wait_writable
andrb_io_maybe_wait
respectively.rb_thread_wait_fd
andrb_thread_fd_writable
are deprecated. [Bug #18003]
Stdlib compatibility issues
-
ERB#initialize
warnssafe_level
and later arguments even without -w. [Feature #14256] -
lib/debug.rb
is replaced withdebug.gem
-
Kernel#pp
inlib/pp.rb
uses the width ofIO#winsize
by default. This means that the output width is automatically changed depending on your terminal size. [Feature #12913]
C API updates
-
Documented. [GH-4815]
-
rb_gc_force_recycle
is deprecated and has been changed to a no-op. [Feature #18290]
Implementation improvements
-
instance_eval
andinstance_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]
JIT
-
The default
--jit-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.
-
--jit-verbose
and--jit-warning
output "JIT cancel" when JIT-ed code is disabled because TracePoint or GC.compact is used. -
RubyVM::MJIT
is renamed toRubyVM::JIT
. [Feature #17490]
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 most real-world software, up to 22% on railsbench, 39% on liquid-render.
-
Fast warm-up times.
-
Limited to macOS & Linux on x86-64 platforms for now.
Static analysis
RBS
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 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 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 location in 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.
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 purpose. Do not use this in production. [Feature #17762] -
Now exceptions raised in finalizers will be printed to
STDERR
, unless$VERBOSE
isnil
. [Feature #17798] -
ruby -run -e httpd
displays URLs to access. [Feature #17847]