-
-
Couldn't load subscription status.
- Fork 392
Description
ruby/spec already contains some specs for 2.7, but we should aim to cover all new features and important changes.
This will improve the test coverage of these features (and maybe discover a few bugs along the way), allow other Ruby implementations to implement the changes faster with more confidence and document clearly the new behavior.
The new specs should be within a version guard block:
ruby_version_is "2.7" do
# New specs
endNOTE: https://rubyreferences.github.io/rubychanges/2.7.html gives more details for many features and changes.
From https://github.com/ruby/ruby/blob/v2_7_0/NEWS:
NEWS for Ruby 2.7.0
This document is a list of user visible feature changes made between
releases except for bug fixes.
Note that each entry is kept so brief that no reason behind or reference
information is supplied with. For a full list of changes with all
sufficient information, see the ChangeLog file or Redmine
(e.g. https://bugs.ruby-lang.org/issues/$FEATURE_OR_BUG_NUMBER).
Changes since the 2.6.0 release
Language changes
Pattern matching
- Pattern matching is introduced as an experimental feature. Feature #14912
case [0, [1, 2, 3]]
in [a, [b, *c]]
p a #=> 0
p b #=> 1
p c #=> [2, 3]
end
case {a: 0, b: 1}
in {a: 0, x: 1}
:unreachable
in {a: 0, b: var}
p var #=> 1
end
case -1
in 0 then :unreachable
in 1 then :unreachable
end #=> NoMatchingPatternError
json = <<END
{
"name": "Alice",
"age": 30,
"children": [{ "name": "Bob", "age": 2 }]
}
END
JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: name, age: age}]}
p name #=> "Bob"
p age #=> 2
JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: "Charlie", age: age}]}
#=> NoMatchingPatternErrorSee the following slides for more details:
- https://speakerdeck.com/k_tsj/pattern-matching-new-feature-in-ruby-2-dot-7
- Note that the slides are slightly obsolete.
- The warning against pattern matching can be suppressed with
{-W:no-experimental option}[#label-Warning+option].
The spec of keyword arguments is changed towards 3.0
-
Non-symbols are allowed as keyword argument keys if the method accepts
arbitrary keywords. Feature #14183Non-Symbol keys in a keyword arguments hash were prohibited in 2.6.0,
but are now allowed again. Bug #15658
def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1}-
**nilis allowed in method definitions to explicitly mark
that the method accepts no keywords. Calling such a method with keywords
will result in an ArgumentError. Feature #14183
def foo(h, **nil); end; foo(key: 1) # ArgumentError
def foo(h, **nil); end; foo(**{key: 1}) # ArgumentError
def foo(h, **nil); end; foo("str" => 1) # ArgumentError
def foo(h, **nil); end; foo({key: 1}) # OK
def foo(h, **nil); end; foo({"str" => 1}) # OK- Passing an empty keyword splat to a method that does not accept keywords
no longer passes an empty hash, unless the empty hash is necessary for
a required parameter, in which case a warning will be emitted. Remove
the double splat to continue passing a positional hash. Feature #14183
h = {}; def foo(*a) a end; foo(**h) # []
h = {}; def foo(a) a end; foo(**h) # {} and warning
h = {}; def foo(*a) a end; foo(h) # [{}]
h = {}; def foo(a) a end; foo(h) # {}- Above warnings can be suppressed also with {-W:no-deprecated option}[#label-Warning+option].
Numbered parameters
-
Numbered parameters as default block parameters are introduced.
Feature #4475[1, 2, 10].map { _1.to_s(16) } #=> ["1", "2", "a"] [[1, 2], [3, 4]].map { _1 + _2 } #=> [3, 7]
You can still define a local variable named
_1and so on,
and that is honored when present, but renders a warning._1 = 0 #=> warning: `_1' is reserved for numbered parameter; consider another name [1].each { p _1 } # prints 0 instead of 1
proc/lambda without block is deprecated
-
Proc.new and Kernel#proc with no block in a method called with a block is
warned now.def foo proc end foo { puts "Hello" } #=> warning: Capturing the given block using Kernel#proc is deprecated; use `&block` instead
This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
-
Kernel#lambda with no block in a method called with a block raises an exception.
def bar lambda end bar { puts "Hello" } #=> tried to create Proc object without a block (ArgumentError)
Other miscellaneous changes
-
A beginless range is experimentally introduced. It might be useful
incase, new call-sequence of theComparable#clamp,
constants and DSLs. Feature #14799ary[..3] # identical to ary[0..3] case RUBY_VERSION when ..."2.4" then puts "EOL" # ... end age.clamp(..100) where(sales: ..100)
-
Quoted here-document identifiers must end within the same line.
<<"EOS " # This had been warned since 2.4; Now it raises a SyntaxError EOS
-
The flip-flop syntax deprecation is reverted. Feature #5400
-
Comment lines can be placed between fluent dot now.
foo # .bar .baz # => foo.baz
-
Calling a private method with a literal
selfas the receiver
is now allowed. Feature #11297 Feature #16123 -
Modifier rescue now operates the same for multiple assignment as single
assignment. Bug #8279a, b = raise rescue [1, 2] # Previously parsed as: (a, b = raise) rescue [1, 2] # Now parsed as: a, b = (raise rescue [1, 2])
-
yieldin singleton class syntax is warned and will be deprecated later. Feature #15575.def foo class << Object.new yield #=> warning: `yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575](https://bugs.ruby-lang.org/issues/15575) end end foo { p :ok }
This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
-
Argument forwarding by
(...)is introduced. Feature #16253def foo(...) bar(...) end
All arguments to
fooare forwarded tobar, including keyword and
block arguments.
Note that the parentheses are mandatory.bar ...is parsed
as an endless range. -
Access and setting of
$SAFEis now always warned.$SAFE
will become a normal global variable in Ruby 3.0. Feature #16131 -
Object#{taint,untaint,trust,untrust}and related functions in the C-API
no longer have an effect (all objects are always considered untainted), and are now
warned in verbose mode. This warning will be disabled even in non-verbose mode in
Ruby 3.0, and the methods and C functions will be removed in Ruby 3.2. Feature #16131 -
Refinements take place at
Object#methodandModule#instance_method. Feature #15373
Command line options
Warning option
The -W option has been extended with a following :, to manage categorized
warnings. Feature #16345 Feature #16420
-
To suppress deprecation warnings:
$ ruby -e '$; = ""' -e:1: warning: `$;' is deprecated $ ruby -W:no-deprecated -e '$; = //' -
It works with the
RUBYOPTenvironment variable:$ RUBYOPT=-W:no-deprecated ruby -e '$; = //' -
To suppress experimental feature warnings:
$ ruby -e '0 in a' -e:1: warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby! $ ruby -W:no-experimental -e '0 in a' -
To suppress both by using
RUBYOPT, set space separated values:$ RUBYOPT='-W:no-deprecated -W:no-experimental' ruby -e '($; = "") in a'
See also Warning in {Core classes updates}[#label-Core+classes+updates+-28outstanding+ones+only-29].
Core classes updates (outstanding ones only)
Array
-
Added Array#intersection. Feature #16155
-
Added Array#minmax, with a faster implementation than Enumerable#minmax. Bug #15929
Comparable
-
Comparable#clamp now accepts a Range argument. Feature #14784
```ruby -1.clamp(0..2) #=> 0 1.clamp(0..2) #=> 1 3.clamp(0..2) #=> 2 # With beginless and endless ranges: -1.clamp(0..) #=> 0 3.clamp(..2) #=> 2 ```
Complex
- Added Complex#<=>.
So0 <=> 0iwill not raise NoMethodError. Bug #15857
Dir
- Dir.glob and Dir.[] no longer allow NUL-separated glob pattern.
Use Array instead. Feature #14643
Encoding
- Added new encoding CESU-8. Feature #15931
Enumerable
-
Added Enumerable#filter_map. Feature #15323
[1, 2, 3].filter_map {|x| x.odd? ? x.to_s : nil } #=> ["1", "3"] -
Added Enumerable#tally. Feature #11076
["A", "B", "C", "B", "A"].tally #=> {"A"=>2, "B"=>2, "C"=>1}
Enumerator
-
Added Enumerator.produce to generate an Enumerator from any custom
data transformation. Feature #14781require "date" dates = Enumerator.produce(Date.today, &:succ) #=> infinite sequence of dates dates.detect(&:tuesday?) #=> next Tuesday -
Added Enumerator::Lazy#eager that generates a non-lazy enumerator
from a lazy enumerator. Feature #15901a = %w(foo bar baz) e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager p e.class #=> Enumerator p e.map {|x| x + "?" } #=> ["FOO!?", "BAR!?", "BAZ!?"] -
Added Enumerator::Yielder#to_proc so that a Yielder object
can be directly passed to another method as a block
argument. Feature #15618
Fiber
- Added Fiber#raise that behaves like Fiber#resume but raises an
exception on the resumed fiber. Feature #10344
File
-
File.extname now returns a dot string for names ending with a dot on
non-Windows platforms. Bug #15267File.extname("foo.") #=> "."
FrozenError
- Added FrozenError#receiver to return the frozen object on which
modification was attempted. To set this object when raising
FrozenError in Ruby code, FrozenError.new accepts a:receiver
option. Feature #15751
GC
-
(MRI-specific) Added GC.compact method for compacting the heap.
This function compacts live objects in the heap so that fewer pages may
be used, and the heap may be more CoW (copy-on-write) friendly. Feature #15626Details on the algorithm and caveats can be found here: https://bugs.ruby-lang.org/issues/15626
IO
- Added IO#set_encoding_by_bom to check the BOM and set the external
encoding. Bug #15210
Integer
-
Integer#[] now supports range operations. Feature #8842
0b01001101[2, 4] #=> 0b0011 0b01001100[2..5] #=> 0b0011 0b01001100[2...6] #=> 0b0011 # ^^^^
Method
- Method#inspect shows more information. Feature #14145
Module
-
Added Module#const_source_location to retrieve the location where a
constant is defined. Feature #10771 -
Added Module#ruby2_keywords for marking a method as passing keyword
arguments through a regular argument splat, useful when delegating
all arguments to another method in a way that can be backwards
compatible with older Ruby versions. Bug #16154 -
Module#autoload? now takes an
inheritoptional argument, like
Module#const_defined?. Feature #15777 -
Module#name now always returns a frozen String. The returned String is
always the same for a given Module. This change is
experimental. Feature #16150
NilClass / TrueClass / FalseClass
- NilClass#to_s, TrueClass#to_s, and FalseClass#to_s now always return a
frozen String. The returned String is always the same for each of these
values. This change is experimental. Feature #16150
ObjectSpace::WeakMap
- ObjectSpace::WeakMap#[]= now accepts special objects as either key or
values. Feature #16035
Proc
- Added Proc#ruby2_keywords for marking the proc as passing keyword
arguments through a regular argument splat, useful when delegating
all arguments to another method or proc in a way that can be backwards
compatible with older Ruby versions. Feature #16404
Range
-
Added Range#minmax, with a faster implementation than Enumerable#minmax.
It returns a maximum that now corresponds to Range#max. Bug #15807 -
Range#=== now uses Range#cover? for String arguments, too (in Ruby 2.6, it was
changed from Range#include? for all types except strings). Bug #15449
String
-
Update Unicode version and Emoji version from 11.0.0 to
12.0.0. Feature #15321 -
Update Unicode version to 12.1.0, adding support for
U+32FF SQUARE ERA NAME REIWA. Feature #15195 -
Update Unicode Emoji version to 12.1. Feature #16272
Symbol
- Added Symbol#start_with? and Symbol#end_with? methods. Feature #16348
Time
-
Added Time#ceil method. Feature #15772
-
Added Time#floor method. Feature #15653
-
Time#inspect is separated from Time#to_s and it shows
the time's sub second. Feature #15958
UnboundMethod
-
Added UnboundMethod#bind_call method. Feature #15955
<code>umethod.bind_call(obj, ...)</code> is semantically equivalent to <code>umethod.bind(obj).call(...)</code>. This idiom is used in some libraries to call a method that is overridden. The added method does the same without allocation of an intermediate Method object. class Foo def add_1(x) x + 1 end end class Bar < Foo def add_1(x) # override x + 2 end end obj = Bar.new p obj.add_1(1) #=> 3 p Foo.instance_method(:add_1).bind(obj).call(1) #=> 2 p Foo.instance_method(:add_1).bind_call(obj, 1) #=> 2
Warning
- Added Warning.[] and Warning.[]= to manage emitting/suppressing
some categories of warnings. Feature #16345 Feature #16420
$LOAD_PATH
- Added
$LOAD_PATH.resolve_feature_path. Feature #15903 Feature #15230
Stdlib updates (outstanding ones only)
- Pathname.glob now delegates 3 arguments to Dir.glob
to acceptbasekeyword. Feature #14405
Compatibility issues (excluding feature bug fixes)
- The following libraries are no longer bundled gems.
Install corresponding gems to use these features.- CMath (cmath gem)
- Scanf (scanf gem)
- Shell (shell gem)
- Synchronizer (sync gem)
- ThreadsWait (thwait gem)
- E2MM (e2mmap gem)
Proc
- The Proc#to_s format was changed. Feature #16101
Range
- Add Range#minmax specs #777 Range#minmax used to iterate on the range to determine the maximum.
It now uses the same algorithm as Range#max. In rare cases (e.g.
ranges of Floats or Strings), this may yield different results. Bug #15807
Stdlib compatibility issues (excluding feature bug fixes)
- Promote stdlib to default gems
- The following default gems were published on rubygems.org
- benchmark
- cgi
- delegate
- getoptlong
- net-pop
- net-smtp
- open3
- pstore
- readline
- readline-ext
- singleton
- The following default gems were only promoted at ruby-core,
but not yet published on rubygems.org.- monitor
- observer
- timeout
- tracer
- uri
- yaml
- The following default gems were published on rubygems.org
- The
did_you_meangem has been promoted up to a default gem from a bundled gem
pathname
- Kernel#Pathname when called with a Pathname argument now returns
the argument instead of creating a new Pathname. This is more
similar to other Kernel methods, but can break code that modifies
the return value and expects the argument not to be modified.
C API updates
-
Many
*_kwfunctions have been added for setting whether
the final argument being passed should be treated as keywords. You
may need to switch to these functions to avoid keyword argument
separation warnings, and to ensure correct behavior in Ruby 3. -
The
:character inrb_scan_argsformat string is now
treated as keyword arguments. Passing a positional hash instead of
keyword arguments will emit a deprecation warning. -
C API declarations with
ANYARGSare changed not to useANYARGS.
See Delete ANYARGS ruby#2404