5 This document is a list of user visible feature changes made between
6 releases except for bug fixes.
8 Note that each entry is kept so brief that no reason behind or reference
9 information is supplied with. For a full list of changes with all
10 sufficient information, see the ChangeLog file or Redmine
11 (e.g. <tt>https://bugs.ruby-lang.org/issues/$FEATURE_OR_BUG_NUMBER</tt>).
13 == Changes since the 2.6.0 release
19 * Pattern matching is introduced as an experimental feature. [Feature #14912]
36 in 0 then :unreachable
37 in 1 then :unreachable
38 end #=> NoMatchingPatternError
44 "children": [{ "name": "Bob", "age": 2 }]
48 JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: name, age: age}]}
53 JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: "Charlie", age: age}]}
54 #=> NoMatchingPatternError
56 * See the following slides for more details:
57 * https://speakerdeck.com/k_tsj/pattern-matching-new-feature-in-ruby-2-dot-7
58 * Note that the slides are slightly obsolete.
60 * The warning against pattern matching can be suppressed with
61 {-W:no-experimental option}[#label-Warning+option].
63 ==== The spec of keyword arguments is changed towards 3.0
65 * Automatic conversion of keyword arguments and positional arguments is
66 deprecated, and conversion will be removed in Ruby 3. [Feature #14183]
68 * When a method call passes a Hash at the last argument, and when it
69 passes no keywords, and when the called method accepts keywords,
70 a warning is emitted. To continue treating the hash as keywords,
71 add a double splat operator to avoid the warning and ensure
72 correct behavior in Ruby 3.
74 def foo(key: 42); end; foo({key: 42}) # warned
75 def foo(**kw); end; foo({key: 42}) # warned
76 def foo(key: 42); end; foo(**{key: 42}) # OK
77 def foo(**kw); end; foo(**{key: 42}) # OK
79 * When a method call passes keywords to a method that accepts keywords,
80 but it does not pass enough required positional arguments, the
81 keywords are treated as a final required positional argument, and a
82 warning is emitted. Pass the argument as a hash instead of keywords
83 to avoid the warning and ensure correct behavior in Ruby 3.
85 def foo(h, **kw); end; foo(key: 42) # warned
86 def foo(h, key: 42); end; foo(key: 42) # warned
87 def foo(h, **kw); end; foo({key: 42}) # OK
88 def foo(h, key: 42); end; foo({key: 42}) # OK
90 * When a method accepts specific keywords but not a keyword splat, and
91 a hash or keywords splat is passed to the method that includes both
92 Symbol and non-Symbol keys, the hash will continue to be split, and
93 a warning will be emitted. You will need to update the calling code
94 to pass separate hashes to ensure correct behavior in Ruby 3.
96 def foo(h={}, key: 42); end; foo("key" => 43, key: 42) # warned
97 def foo(h={}, key: 42); end; foo({"key" => 43, key: 42}) # warned
98 def foo(h={}, key: 42); end; foo({"key" => 43}, key: 42) # OK
100 * If a method does not accept keywords, and is called with keywords,
101 the keywords are still treated as a positional hash, with no warning.
102 This behavior will continue to work in Ruby 3.
104 def foo(opt={}); end; foo( key: 42 ) # OK
106 * Non-symbols are allowed as keyword argument keys if the method accepts
107 arbitrary keywords. [Feature #14183]
109 * Non-Symbol keys in a keyword arguments hash were prohibited in 2.6.0,
110 but are now allowed again. [Bug #15658]
112 def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1}
114 * <code>**nil</code> is allowed in method definitions to explicitly mark
115 that the method accepts no keywords. Calling such a method with keywords
116 will result in an ArgumentError. [Feature #14183]
118 def foo(h, **nil); end; foo(key: 1) # ArgumentError
119 def foo(h, **nil); end; foo(**{key: 1}) # ArgumentError
120 def foo(h, **nil); end; foo("str" => 1) # ArgumentError
121 def foo(h, **nil); end; foo({key: 1}) # OK
122 def foo(h, **nil); end; foo({"str" => 1}) # OK
124 * Passing an empty keyword splat to a method that does not accept keywords
125 no longer passes an empty hash, unless the empty hash is necessary for
126 a required parameter, in which case a warning will be emitted. Remove
127 the double splat to continue passing a positional hash. [Feature #14183]
129 h = {}; def foo(*a) a end; foo(**h) # []
130 h = {}; def foo(a) a end; foo(**h) # {} and warning
131 h = {}; def foo(*a) a end; foo(h) # [{}]
132 h = {}; def foo(a) a end; foo(h) # {}
134 * Above warnings can be suppressed also with {-W:no-deprecated option}[#label-Warning+option].
136 ==== Numbered parameters
138 * Numbered parameters as default block parameters are introduced. [Feature #4475]
140 [1, 2, 10].map { _1.to_s(16) } #=> ["1", "2", "a"]
141 [[1, 2], [3, 4]].map { _1 + _2 } #=> [3, 7]
143 You can still define a local variable named +_1+ and so on,
144 and that is honored when present, but renders a warning.
146 _1 = 0 #=> warning: `_1' is reserved for numbered parameter; consider another name
147 [1].each { p _1 } # prints 0 instead of 1
149 ==== proc/lambda without block is deprecated
151 * Proc.new and Kernel#proc with no block in a method called with a block will
152 now display a warning.
157 foo { puts "Hello" } #=> warning: Capturing the given block using Kernel#proc is deprecated; use `&block` instead
159 This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
161 * Kernel#lambda with no block in a method called with a block raises an exception.
166 bar { puts "Hello" } #=> tried to create Proc object without a block (ArgumentError)
168 ==== Other miscellaneous changes
170 * A beginless range is experimentally introduced. It might be useful
171 in +case+, new call-sequence of the <code>Comparable#clamp</code>,
172 constants and DSLs. [Feature #14799]
174 ary[..3] # identical to ary[0..3]
177 when ..."2.4" then puts "EOL"
185 * Setting <code>$;</code> to a non-nil value will now display a warning. [Feature #14240]
186 This includes the usage in String#split.
187 This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
189 * Setting <code>$,</code> to a non-nil value will now display a warning. [Feature #14240]
190 This includes the usage in Array#join.
191 This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
193 * Quoted here-document identifiers must end within the same line.
196 " # This had been warned since 2.4; Now it raises a SyntaxError
199 * The flip-flop syntax deprecation is reverted. [Feature #5400]
201 * Comment lines can be placed between fluent dot now.
207 * Calling a private method with a literal +self+ as the receiver
208 is now allowed. [Feature #11297] [Feature #16123]
210 * Modifier rescue now operates the same for multiple assignment as single
211 assignment. [Bug #8279]
213 a, b = raise rescue [1, 2]
214 # Previously parsed as: (a, b = raise) rescue [1, 2]
215 # Now parsed as: a, b = (raise rescue [1, 2])
217 * +yield+ in singleton class syntax will now display a warning. This behavior
218 will soon be deprecated. [Feature #15575].
222 yield #=> warning: `yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575]
227 This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
229 * Argument forwarding by <code>(...)</code> is introduced. [Feature #16253]
235 All arguments to +foo+ are forwarded to +bar+, including keyword and
237 Note that the parentheses are mandatory. <code>bar ...</code> is parsed
240 * Access and setting of <code>$SAFE</code> will now always display a warning.
241 <code>$SAFE</code> will become a normal global variable in Ruby 3.0. [Feature #16131]
243 * <code>Object#{taint,untaint,trust,untrust}</code> and related functions in the C-API
244 no longer have an effect (all objects are always considered untainted), and will now
245 display a warning in verbose mode. This warning will be disabled even in non-verbose mode in
246 Ruby 3.0, and the methods and C functions will be removed in Ruby 3.2. [Feature #16131]
248 * Refinements take place at Object#method and Module#instance_method. [Feature #15373]
250 === Command line options
254 The +-W+ option has been extended with a following +:+, to manage categorized
255 warnings. [Feature #16345] [Feature #16420]
257 * To suppress deprecation warnings:
260 -e:1: warning: `$;' is deprecated
262 $ ruby -W:no-deprecated -e '$; = //'
264 * It works with the +RUBYOPT+ environment variable:
266 $ RUBYOPT=-W:no-deprecated ruby -e '$; = //'
268 * To suppress experimental feature warnings:
271 -e:1: warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!
273 $ ruby -W:no-experimental -e '0 in a'
275 * To suppress both by using +RUBYOPT+, set space separated values:
277 $ RUBYOPT='-W:no-deprecated -W:no-experimental' ruby -e '($; = "") in a'
279 See also Warning in {Core classes updates}[#label-Core+classes+updates+-28outstanding+ones+only-29].
281 === Core classes updates (outstanding ones only)
287 * Added Array#intersection. [Feature #16155]
289 * Added Array#minmax, with a faster implementation than Enumerable#minmax. [Bug #15929]
295 * Comparable#clamp now accepts a Range argument. [Feature #14784]
300 # With beginless and endless ranges:
310 So <code>0 <=> 0i</code> will not raise NoMethodError. [Bug #15857]
316 * Dir.glob and Dir.[] no longer allow NUL-separated glob pattern.
317 Use Array instead. [Feature #14643]
323 * Added new encoding CESU-8. [Feature #15931]
329 * Added Enumerable#filter_map. [Feature #15323]
331 [1, 2, 3].filter_map {|x| x.odd? ? x.to_s : nil } #=> ["1", "3"]
333 * Added Enumerable#tally. [Feature #11076]
335 ["A", "B", "C", "B", "A"].tally #=> {"A"=>2, "B"=>2, "C"=>1}
341 * Added Enumerator.produce to generate an Enumerator from any custom
342 data transformation. [Feature #14781]
345 dates = Enumerator.produce(Date.today, &:succ) #=> infinite sequence of dates
346 dates.detect(&:tuesday?) #=> next Tuesday
348 * Added Enumerator::Lazy#eager that generates a non-lazy enumerator
349 from a lazy enumerator. [Feature #15901]
352 e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager
353 p e.class #=> Enumerator
354 p e.map {|x| x + "?" } #=> ["FOO!?", "BAR!?", "BAZ!?"]
356 * Added Enumerator::Yielder#to_proc so that a Yielder object
357 can be directly passed to another method as a block
358 argument. [Feature #15618]
360 * Added Enumerator::Lazy#with_index be lazy
361 Previously, Enumerator::Lazy#with_index was not defined, so it
362 picked up the default implementation from Enumerator, which was
363 not lazy. [Bug #7877]
365 ("a"..).lazy.with_index(1) { |it, index| puts "#{index}:#{it}" }.take(3).force
374 * Added Fiber#raise that behaves like Fiber#resume but raises an
375 exception on the resumed fiber. [Feature #10344]
381 * Added File.absolute_path? to check whether a path is absolute or
382 not in a portable way. [Feature #15868]
384 File.absolute_path?("/foo") # => true (on *nix)
385 File.absolute_path?("C:/foo") # => true (on Windows)
386 File.absolute_path?("foo") # => false
390 * File.extname now returns a dot string for names ending with a dot on
391 non-Windows platforms. [Bug #15267]
393 File.extname("foo.") #=> "."
399 * Added FrozenError#receiver to return the frozen object on which
400 modification was attempted. To set this object when raising
401 FrozenError in Ruby code, FrozenError.new accepts a +:receiver+
402 option. [Feature #15751]
408 * Added GC.compact method for compacting the heap.
409 This function compacts live objects in the heap so that fewer pages may
410 be used, and the heap may be more CoW (copy-on-write) friendly. [Feature #15626]
412 Details on the algorithm and caveats can be found here:
413 https://bugs.ruby-lang.org/issues/15626
419 * Added IO#set_encoding_by_bom to check the BOM and set the external
420 encoding. [Bug #15210]
426 * Integer#[] now supports range operations. [Feature #8842]
428 0b01001101[2, 4] #=> 0b0011
429 0b01001100[2..5] #=> 0b0011
430 0b01001100[2...6] #=> 0b0011
437 * Method#inspect shows more information. [Feature #14145]
443 * Added Module#const_source_location to retrieve the location where a
444 constant is defined. [Feature #10771]
446 * Added Module#ruby2_keywords for marking a method as passing keyword
447 arguments through a regular argument splat, useful when delegating
448 all arguments to another method in a way that can be backwards
449 compatible with older Ruby versions. [Bug #16154]
453 * Module#autoload? now takes an +inherit+ optional argument, like
454 Module#const_defined?. [Feature #15777]
456 * Module#name now always returns a frozen String. The returned String is
457 always the same for a given Module. This change is
458 experimental. [Feature #16150]
460 [NilClass / TrueClass / FalseClass]
464 * NilClass#to_s, TrueClass#to_s, and FalseClass#to_s now always return a
465 frozen String. The returned String is always the same for each of these
466 values. This change is experimental. [Feature #16150]
468 [ObjectSpace::WeakMap]
472 * ObjectSpace::WeakMap#[]= now accepts special objects as either key or
473 values. [Feature #16035]
479 * Added Proc#ruby2_keywords for marking the proc as passing keyword
480 arguments through a regular argument splat, useful when delegating
481 all arguments to another method or proc in a way that can be backwards
482 compatible with older Ruby versions. [Feature #16404]
488 * Added Range#minmax, with a faster implementation than Enumerable#minmax.
489 It returns a maximum that now corresponds to Range#max. [Bug #15807]
493 * Range#=== now uses Range#cover? for String arguments, too (in Ruby 2.6, it was
494 changed from Range#include? for all types except strings). [Bug #15449]
501 * +RubyVM.resolve_feature_path+ moved to
502 <code>$LOAD_PATH.resolve_feature_path</code>. [Feature #15903] [Feature #15230]
508 * Update Unicode version and Emoji version from 11.0.0 to
509 12.0.0. [Feature #15321]
511 * Update Unicode version to 12.1.0, adding support for
512 U+32FF SQUARE ERA NAME REIWA. [Feature #15195]
514 * Update Unicode Emoji version to 12.1. [Feature #16272]
520 * Added Symbol#start_with? and Symbol#end_with? methods. [Feature #16348]
526 * Added Time#ceil method. [Feature #15772]
528 * Added Time#floor method. [Feature #15653]
532 * Time#inspect is separated from Time#to_s and it shows
533 the time's sub second. [Feature #15958]
539 * Added UnboundMethod#bind_call method. [Feature #15955]
541 <code>umethod.bind_call(obj, ...)</code> is semantically equivalent
542 to <code>umethod.bind(obj).call(...)</code>. This idiom is used in
543 some libraries to call a method that is overridden. The added
544 method does the same without allocation of an intermediate Method
553 def add_1(x) # override
560 p Foo.instance_method(:add_1).bind(obj).call(1) #=> 2
561 p Foo.instance_method(:add_1).bind_call(obj, 1) #=> 2
567 * Added Warning.[] and Warning.[]= to manage emitting/suppressing
568 some categories of warnings. [Feature #16345] [Feature #16420]
574 * Added <code>$LOAD_PATH.resolve_feature_path</code>. [Feature #15903] [Feature #15230]
576 === Stdlib updates (outstanding ones only)
580 * Upgrade to Bundler 2.1.2.
581 See https://github.com/bundler/bundler/releases/tag/v2.1.2
585 * CGI.escapeHTML becomes 2~5x faster when there is at least one escaped character.
586 See https://github.com/ruby/ruby/pull/2226
591 See https://github.com/ruby/csv/blob/master/NEWS.md.
595 * Date.jisx0301, Date#jisx0301, and Date.parse support the new Japanese
596 era. [Feature #15742]
600 * Object#DelegateClass accepts a block and module_evals it in the context
601 of the returned class, similar to Class.new and Struct.new.
605 * Prohibit marshaling ERB instance.
609 * Introduce syntax highlighting inspired by the Pry gem to Binding#irb
610 source lines, REPL input, and inspect output of some core-class objects.
612 * Introduce multiline editing mode provided by Reline.
614 * Show documentation when completion.
616 * Enable auto indent and save/load history by default.
624 * Add Net::FTP#features to check available features, and Net::FTP#option to
625 enable/disable each of them. [Feature #15964]
629 * Add +ipaddr+ optional parameter to Net::HTTP#start to replace the address for
630 the TCP/IP connection. [Feature #5180]
634 * Add Server Name Indication (SNI) support. [Feature #15594]
638 * Warn open-uri's "open" method at Kernel.
639 Use URI.open instead. [Misc #15893]
641 * The default charset of "text/*" media type is UTF-8 instead of
642 ISO-8859-1. [Bug #15933]
646 * Now show "Did you mean?" for unknown options. [Feature #16256]
651 OptionParser.new do |opts|
652 opts.on("-f", "--foo", "foo") {|v| }
653 opts.on("-b", "--bar", "bar") {|v| }
654 opts.on("-c", "--baz", "baz") {|v| }
660 Traceback (most recent call last):
661 test.rb:7:in `<main>': invalid option: --baa (OptionParser::InvalidOption)
667 * Pathname.glob now delegates 3 arguments to Dir.glob
668 to accept +base+ keyword. [Feature #14405]
672 * Merge 1.4.15 from upstream repository and added cli of racc.
676 * New stdlib that is compatible with the readline stdlib but is
677 implemented in pure Ruby. It also provides a multiline editing mode.
682 See https://github.com/ruby/rexml/blob/master/NEWS.md.
686 * Upgrade to RSS 0.2.8.
687 See https://github.com/ruby/rss/blob/master/NEWS.md.
691 * Upgrade to RubyGems 3.1.2.
692 * https://github.com/rubygems/rubygems/releases/tag/v3.1.0
693 * https://github.com/rubygems/rubygems/releases/tag/v3.1.1
694 * https://github.com/rubygems/rubygems/releases/tag/v3.1.2
699 See https://github.com/ruby/strscan/blob/master/NEWS.md.
701 === Compatibility issues (excluding feature bug fixes)
703 * The following libraries are no longer bundled gems.
704 Install corresponding gems to use these features.
708 * Synchronizer (sync gem)
709 * ThreadsWait (thwait gem)
713 * The Proc#to_s format was changed. [Feature #16101]
716 * Range#minmax used to iterate on the range to determine the maximum.
717 It now uses the same algorithm as Range#max. In rare cases (e.g.
718 ranges of Floats or Strings), this may yield different results. [Bug #15807]
720 === Stdlib compatibility issues (excluding feature bug fixes)
722 * Promote stdlib to default gems
723 * The following default gems were published on rubygems.org
735 * The following default gems were only promoted at ruby-core,
736 but not yet published on rubygems.org.
743 * The <tt>did_you_mean</tt> gem has been promoted up to a default gem from a bundled gem
747 * Kernel#Pathname when called with a Pathname argument now returns
748 the argument instead of creating a new Pathname. This is more
749 similar to other Kernel methods, but can break code that modifies
750 the return value and expects the argument not to be modified.
752 [profile.rb, Profiler__]
754 * Removed from standard library. It was unmaintained since Ruby 2.0.0.
758 * Many <code>*_kw</code> functions have been added for setting whether
759 the final argument being passed should be treated as keywords. You
760 may need to switch to these functions to avoid keyword argument
761 separation warnings, and to ensure correct behavior in Ruby 3.
763 * The <code>:</code> character in rb_scan_args format string is now
764 treated as keyword arguments. Passing a positional hash instead of
765 keyword arguments will emit a deprecation warning.
767 * C API declarations with +ANYARGS+ are changed not to use +ANYARGS+.
768 See https://github.com/ruby/ruby/pull/2404
770 === Implementation improvements
774 * Allow selecting different coroutine implementations by using
775 +--with-coroutine=+, e.g.
777 $ ./configure --with-coroutine=ucontext
778 $ ./configure --with-coroutine=copy
780 * Replace previous stack cache with fiber pool cache. The fiber pool
781 allocates many stacks in a single memory region. Stack allocation
782 becomes O(log N) and fiber creation is amortized O(1). Around 10x
783 performance improvement was measured in micro-benchmarks.
784 https://github.com/ruby/ruby/pull/2224
787 * File.realpath now uses realpath(3) on many platforms, which can
788 significantly improve performance. [Feature #15797]
791 * Change data structure of small Hash objects. [Feature #15602]
794 * Monitor class is written in C-extension. [Feature #16255]
798 * VM stack memory allocation is now combined with native thread stack,
799 improving thread allocation performance and reducing allocation related
800 failures. Around 10x performance improvement was measured in micro-benchmarks.
804 * JIT-ed code is recompiled to less-optimized code when an optimization assumption is invalidated.
806 * Method inlining is performed when a method is considered as pure.
807 This optimization is still experimental and many methods are NOT considered as pure yet.
809 * The default value of +--jit-max-cache+ is changed from 1,000 to 100.
811 * The default value of +--jit-min-calls+ is changed from 5 to 10,000.
815 * Per-call-site method cache, which has been there since around 1.9, was
816 improved: cache hit rate raised from 89% to 94%.
817 See https://github.com/ruby/ruby/pull/2583
819 [RubyVM::InstructionSequence]
821 * RubyVM::InstructionSequence#to_binary method generates compiled binary.
822 The binary size is reduced. [Feature #16163]
824 === Miscellaneous changes
826 * Support for IA64 architecture has been removed. Hardware for testing was
827 difficult to find, native fiber code is difficult to implement, and it added
828 non-trivial complexity to the interpreter. [Feature #15894]
830 * Require compilers to support C99. [Misc #15347]
832 * Details of our dialect: https://bugs.ruby-lang.org/projects/ruby-master/wiki/C99
834 * Ruby's upstream repository is changed from Subversion to Git.
836 * https://git.ruby-lang.org/ruby.git
838 * RUBY_REVISION class is changed from Integer to String.
840 * RUBY_DESCRIPTION includes Git revision instead of Subversion's one.
842 * Support built-in methods in Ruby with the <code>_\_builtin_</code> syntax. [Feature #16254]
844 Some methods are defined in *.rb (such as trace_point.rb).
845 For example, it is easy to define a method which accepts keyword arguments.