diff options
author | Benoit Daloze <[email protected]> | 2023-06-26 15:55:11 +0200 |
---|---|---|
committer | Benoit Daloze <[email protected]> | 2023-06-26 15:55:11 +0200 |
commit | 515bd4214497b3af02f6eef51b496ad9a0cf6b3b () | |
tree | 4554360d275a3bb9dc696f952b8f3d1bcd88f18a /spec/ruby/language | |
parent | f73fa299279ac322bd921691d1ba0e8bf2b39b5f (diff) |
Update to ruby/spec@30e1c35
22 files changed, 730 insertions, 1466 deletions
@@ -53,66 +53,18 @@ describe "A block yielded a single" do end end - ruby_version_is ''..."3.0" do - it "assigns elements to mixed argument types" do - suppress_keyword_warning do - result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] } - result.should == [1, 2, [], 3, 2, {x: 9}] - end - end - - it "assigns symbol keys from a Hash to keyword arguments" do - suppress_keyword_warning do - result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] } - result.should == [{"a" => 1}, a: 10] - end - end - - it "assigns symbol keys from a Hash returned by #to_hash to keyword arguments" do - suppress_keyword_warning do - obj = mock("coerce block keyword arguments") - obj.should_receive(:to_hash).and_return({"a" => 1, b: 2}) - - result = m([obj]) { |a=nil, **b| [a, b] } - result.should == [{"a" => 1}, b: 2] - end - end end - ruby_version_is "3.0" do - it "assigns elements to mixed argument types" do - result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] } - result.should == [1, 2, [3], {x: 9}, 2, {}] - end - - it "does not treat final Hash as keyword arguments and does not autosplat" do - result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] } - result.should == [[{"a" => 1, a: 10}], {}] - end - - it "does not call #to_hash on final argument to get keyword arguments and does not autosplat" do - suppress_keyword_warning do - obj = mock("coerce block keyword arguments") - obj.should_not_receive(:to_hash) - - result = m([obj]) { |a=nil, **b| [a, b] } - result.should == [[obj], {}] - end - end - end - - ruby_version_is ""...'3.0' do - it "calls #to_hash on the argument but ignores result when optional argument and keyword argument accepted" do - obj = mock("coerce block keyword arguments") - obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2}) - - result = m([obj]) { |a=nil, **b| [a, b] } - result.should == [obj, {}] - end end - ruby_version_is "3.0" do - it "does not call #to_hash on the argument when optional argument and keyword argument accepted and does not autosplat" do obj = mock("coerce block keyword arguments") obj.should_not_receive(:to_hash) @@ -121,102 +73,42 @@ describe "A block yielded a single" do end end - describe "when non-symbol keys are in a keyword arguments Hash" do - ruby_version_is ""..."3.0" do - it "separates non-symbol keys and symbol keys" do - suppress_keyword_warning do - result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] } - result.should == [{"a" => 10}, {b: 2}] - end - end - end - ruby_version_is "3.0" do - it "does not separate non-symbol keys and symbol keys and does not autosplat" do - suppress_keyword_warning do - result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] } - result.should == [[{"a" => 10, b: 2}], {}] - end - end - end - end - - ruby_version_is ""..."3.0" do - it "does not treat hashes with string keys as keyword arguments" do - result = m(["a" => 10]) { |a = nil, **b| [a, b] } - result.should == [{"a" => 10}, {}] - end - end - ruby_version_is "3.0" do - it "does not treat hashes with string keys as keyword arguments and does not autosplat" do - result = m(["a" => 10]) { |a = nil, **b| [a, b] } - result.should == [[{"a" => 10}], {}] - end end - ruby_version_is ''...'3.0' do - it "calls #to_hash on the last element if keyword arguments are present" do - suppress_keyword_warning do - obj = mock("destructure block keyword arguments") - obj.should_receive(:to_hash).and_return({x: 9}) - - result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] } - result.should == [1, [2], 3, {x: 9}] - end - end - - it "assigns the last element to a non-keyword argument if #to_hash returns nil" do - suppress_keyword_warning do - obj = mock("destructure block keyword arguments") - obj.should_receive(:to_hash).and_return(nil) - - result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] } - result.should == [1, [2, 3], obj, {}] - end - end - - it "calls #to_hash on the last element when there are more arguments than parameters" do suppress_keyword_warning do - x = mock("destructure matching block keyword argument") - x.should_receive(:to_hash).and_return({x: 9}) - - result = m([1, 2, 3, {y: 9}, 4, 5, x]) { |a, b=5, c, **k| [a, b, c, k] } - result.should == [1, 2, 3, {x: 9}] end end - it "raises a TypeError if #to_hash does not return a Hash" do - obj = mock("destructure block keyword arguments") - obj.should_receive(:to_hash).and_return(1) - - -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(TypeError) - end - - it "raises the error raised inside #to_hash" do - obj = mock("destructure block keyword arguments") - error = RuntimeError.new("error while converting to a hash") - obj.should_receive(:to_hash).and_raise(error) - - -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(error) - end end - ruby_version_is '3.0' do - it "does not call #to_hash on the last element if keyword arguments are present" do - obj = mock("destructure block keyword arguments") - obj.should_not_receive(:to_hash) - result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] } - result.should == [1, [2, 3], obj, {}] - end - it "does not call #to_hash on the last element when there are more arguments than parameters" do - x = mock("destructure matching block keyword argument") - x.should_not_receive(:to_hash) - result = m([1, 2, 3, {y: 9}, 4, 5, x]) { |a, b=5, c, **k| [a, b, c, k] } - result.should == [1, 2, 3, {}] - end end it "does not call #to_ary on the Array" do @@ -308,20 +308,10 @@ describe "A class definition extending an object (sclass)" do -> { class TestClass < BasicObject.new; end }.should raise_error(TypeError, error_msg) end - ruby_version_is ""..."3.0" do - it "allows accessing the block of the original scope" do - suppress_warning do - ClassSpecs.sclass_with_block { 123 }.should == 123 - end - end - end - - ruby_version_is "3.0" do - it "does not allow accessing the block of the original scope" do - -> { - ClassSpecs.sclass_with_block { 123 } - }.should raise_error(SyntaxError) - end end it "can use return to cause the enclosing method to return" do @@ -83,34 +83,32 @@ describe 'A class variable definition' do end end -ruby_version_is "3.0" do - describe 'Accessing a class variable' do - it "raises a RuntimeError when accessed from the toplevel scope (not in some module or class)" do - -> { - eval "@@cvar_toplevel1" - }.should raise_error(RuntimeError, 'class variable access from toplevel') - -> { - eval "@@cvar_toplevel2 = 2" - }.should raise_error(RuntimeError, 'class variable access from toplevel') - end - - it "does not raise an error when checking if defined from the toplevel scope" do - -> { - eval "defined?(@@cvar_toplevel1)" - }.should_not raise_error - end - - it "raises a RuntimeError when a class variable is overtaken in an ancestor class" do - parent = Class.new() - subclass = Class.new(parent) - subclass.class_variable_set(:@@cvar_overtaken, :subclass) - parent.class_variable_set(:@@cvar_overtaken, :parent) - - -> { - subclass.class_variable_get(:@@cvar_overtaken) - }.should raise_error(RuntimeError, /class variable @@cvar_overtaken of .+ is overtaken by .+/) - - parent.class_variable_get(:@@cvar_overtaken).should == :parent - end end end @@ -170,34 +170,32 @@ describe "Literal (A::X) constant resolution" do -> { ConstantSpecs::ParentA::CS_CONSTX }.should raise_error(NameError) end - ruby_version_is "3.0" do - it "uses the module or class #name to craft the error message" do - mod = Module.new do - def self.name - "ModuleName" - end - - def self.inspect - "<unusable info>" - end end - -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant ModuleName::DOES_NOT_EXIST/) end - it "uses the module or class #inspect to craft the error message if they are anonymous" do - mod = Module.new do - def self.name - nil - end - def self.inspect - "<unusable info>" - end end - -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant <unusable info>::DOES_NOT_EXIST/) end end it "sends #const_missing to the original class or module scope" do @@ -180,6 +180,32 @@ describe "The defined? keyword when called with a method name" do ScratchPad.recorded.should == :defined_specs_fixnum_method end end end describe "The defined? keyword for an expression" do @@ -220,30 +220,15 @@ describe "The ** operator" do h.should == { one: 1, two: 2 } end - ruby_version_is ""..."3.0" do - it "makes a caller-side copy when calling a method taking a positional Hash" do - def m(h) - h.delete(:one); h - end - - h = { one: 1, two: 2 } - m(**h).should == { two: 2 } - m(**h).should_not.equal?(h) - h.should == { one: 1, two: 2 } end - end - ruby_version_is "3.0" do - it "does not copy when calling a method taking a positional Hash" do - def m(h) - h.delete(:one); h - end - - h = { one: 1, two: 2 } - m(**h).should == { two: 2 } - m(**h).should.equal?(h) - h.should == { two: 2 } - end end ruby_version_is "3.1" do @@ -1,286 +1,371 @@ require_relative '../spec_helper' -ruby_version_is "3.0" do - describe "Keyword arguments" do - def target(*args, **kwargs) [args, kwargs] end - it "are separated from positional arguments" do - def m(*args, **kwargs) - [args, kwargs] - end - empty = {} - m(**empty).should == [[], {}] - m(empty).should == [[{}], {}] - m(a: 1).should == [[], {a: 1}] - m({a: 1}).should == [[{a: 1}], {}] end - it "when the receiving method has not keyword parameters it treats kwargs as positional" do def m(*a) a end - m(a: 1).should == [{a: 1}] - m({a: 1}).should == [{a: 1}] end - context "empty kwargs are treated as if they were not passed" do - it "when calling a method" do - def m(*a) - a - end - - empty = {} - m(**empty).should == [] - m(empty).should == [{}] end - it "when yielding to a block" do - def y(*args, **kwargs) - yield(*args, **kwargs) - end - empty = {} - y(**empty) { |*a| a }.should == [] - y(empty) { |*a| a }.should == [{}] - end end - it "extra keywords are not allowed without **kwrest" do - def m(*a, kw:) - a - end - m(kw: 1).should == [] - -> { m(kw: 1, kw2: 2) }.should raise_error(ArgumentError, 'unknown keyword: :kw2') - -> { m(kw: 1, true => false) }.should raise_error(ArgumentError, 'unknown keyword: true') - -> { m(kw: 1, a: 1, b: 2, c: 3) }.should raise_error(ArgumentError, 'unknown keywords: :a, :b, :c') end - it "raises ArgumentError exception when required keyword argument is not passed" do - def m(a:, b:, c:) - [a, b, c] end - -> { m(a: 1, b: 2) }.should raise_error(ArgumentError, /missing keyword: :c/) - -> { m() }.should raise_error(ArgumentError, /missing keywords: :a, :b, :c/) end - it "raises ArgumentError for missing keyword arguments even if there are extra ones" do - def m(a:) - a end - -> { m(b: 1) }.should raise_error(ArgumentError, /missing keyword: :a/) end - it "handle * and ** at the same call site" do - def m(*a) - a end - m(*[], **{}).should == [] - m(*[], 42, **{}).should == [42] end - context "**" do - it "does not copy a non-empty Hash for a method taking (*args)" do - def m(*args) - args[0] - end - h = {a: 1} - m(**h).should.equal?(h) end - it "copies the given Hash for a method taking (**kwargs)" do - def m(**kw) - kw - end - empty = {} - m(**empty).should == empty - m(**empty).should_not.equal?(empty) - h = {a: 1} - m(**h).should == h - m(**h).should_not.equal?(h) end end - context "delegation" do - it "works with (*args, **kwargs)" do - def m(*args, **kwargs) - target(*args, **kwargs) end - empty = {} - m(**empty).should == [[], {}] - m(empty).should == [[{}], {}] - m(a: 1).should == [[], {a: 1}] - m({a: 1}).should == [[{a: 1}], {}] - end - it "works with proc { |*args, **kwargs| }" do - m = proc do |*args, **kwargs| - target(*args, **kwargs) - end - empty = {} - m.(**empty).should == [[], {}] - m.(empty).should == [[{}], {}] - m.(a: 1).should == [[], {a: 1}] - m.({a: 1}).should == [[{a: 1}], {}] - # no autosplatting for |*args, **kwargs| - m.([1, 2]).should == [[[1, 2]], {}] end - it "works with -> (*args, **kwargs) {}" do - m = -> *args, **kwargs do - target(*args, **kwargs) end - empty = {} - m.(**empty).should == [[], {}] - m.(empty).should == [[{}], {}] - m.(a: 1).should == [[], {a: 1}] - m.({a: 1}).should == [[{a: 1}], {}] - end - it "works with (...)" do - instance_eval <<~DEF - def m(...) - target(...) - end - DEF - empty = {} - m(**empty).should == [[], {}] - m(empty).should == [[{}], {}] - m(a: 1).should == [[], {a: 1}] - m({a: 1}).should == [[{a: 1}], {}] end - it "works with call(*ruby2_keyword_args)" do - class << self - ruby2_keywords def m(*args) - target(*args) - end end - empty = {} - m(**empty).should == [[], {}] - Hash.ruby2_keywords_hash?(empty).should == false - m(empty).should == [[{}], {}] - Hash.ruby2_keywords_hash?(empty).should == false - m(a: 1).should == [[], {a: 1}] - m({a: 1}).should == [[{a: 1}], {}] - kw = {a: 1} - m(**kw).should == [[], {a: 1}] - m(**kw)[1].should == kw - m(**kw)[1].should_not.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false - Hash.ruby2_keywords_hash?(m(**kw)[1]).should == false - m(kw).should == [[{a: 1}], {}] - m(kw)[0][0].should.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false - end - it "works with super(*ruby2_keyword_args)" do - parent = Class.new do - def m(*args, **kwargs) - [args, kwargs] - end end - child = Class.new(parent) do - ruby2_keywords def m(*args) - super(*args) - end end - obj = child.new - empty = {} - obj.m(**empty).should == [[], {}] - Hash.ruby2_keywords_hash?(empty).should == false - obj.m(empty).should == [[{}], {}] - Hash.ruby2_keywords_hash?(empty).should == false - obj.m(a: 1).should == [[], {a: 1}] - obj.m({a: 1}).should == [[{a: 1}], {}] - kw = {a: 1} - obj.m(**kw).should == [[], {a: 1}] - obj.m(**kw)[1].should == kw - obj.m(**kw)[1].should_not.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false - Hash.ruby2_keywords_hash?(obj.m(**kw)[1]).should == false - obj.m(kw).should == [[{a: 1}], {}] - obj.m(kw)[0][0].should.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false end - it "works with zsuper" do - parent = Class.new do - def m(*args, **kwargs) - [args, kwargs] end end - child = Class.new(parent) do ruby2_keywords def m(*args) - super end end - obj = child.new - empty = {} - obj.m(**empty).should == [[], {}] - Hash.ruby2_keywords_hash?(empty).should == false - obj.m(empty).should == [[{}], {}] - Hash.ruby2_keywords_hash?(empty).should == false - - obj.m(a: 1).should == [[], {a: 1}] - obj.m({a: 1}).should == [[{a: 1}], {}] - - kw = {a: 1} - - obj.m(**kw).should == [[], {a: 1}] - obj.m(**kw)[1].should == kw - obj.m(**kw)[1].should_not.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false - Hash.ruby2_keywords_hash?(obj.m(**kw)[1]).should == false - obj.m(kw).should == [[{a: 1}], {}] - obj.m(kw)[0][0].should.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false end - it "works with yield(*ruby2_keyword_args)" do class << self - def y(args) - yield(*args) end - ruby2_keywords def m(*outer_args) - y(outer_args, &-> *args, **kwargs { target(*args, **kwargs) }) end end @@ -305,93 +390,6 @@ ruby_version_is "3.0" do m(kw)[0][0].should.equal?(kw) Hash.ruby2_keywords_hash?(kw).should == false end - - it "does not work with (*args)" do - class << self - def m(*args) - target(*args) - end - end - - empty = {} - m(**empty).should == [[], {}] - m(empty).should == [[{}], {}] - - m(a: 1).should == [[{a: 1}], {}] - m({a: 1}).should == [[{a: 1}], {}] - end - - ruby_version_is "3.1" do - describe "omitted values" do - it "accepts short notation 'key' for 'key: value' syntax" do - def m(a:, b:) - [a, b] - end - - a = 1 - b = 2 - - eval('m(a:, b:).should == [1, 2]') - end - end - end - - ruby_version_is "3.2" do - it "does not work with call(*ruby2_keyword_args) with missing ruby2_keywords in between" do - class << self - def n(*args) # Note the missing ruby2_keywords here - target(*args) - end - - ruby2_keywords def m(*args) - n(*args) - end - end - - empty = {} - m(**empty).should == [[], {}] - m(empty).should == [[{}], {}] - - m(a: 1).should == [[{a: 1}], {}] - m({a: 1}).should == [[{a: 1}], {}] - end - end - - ruby_version_is ""..."3.2" do - # https://bugs.ruby-lang.org/issues/18625 - it "works with call(*ruby2_keyword_args) with missing ruby2_keywords in between due to CRuby bug #18625" do - class << self - def n(*args) # Note the missing ruby2_keywords here - target(*args) - end - - ruby2_keywords def m(*args) - n(*args) - end - end - - empty = {} - m(**empty).should == [[], {}] - Hash.ruby2_keywords_hash?(empty).should == false - m(empty).should == [[{}], {}] - Hash.ruby2_keywords_hash?(empty).should == false - - m(a: 1).should == [[], {a: 1}] - m({a: 1}).should == [[{a: 1}], {}] - - kw = {a: 1} - - m(**kw).should == [[], {a: 1}] - m(**kw)[1].should == kw - m(**kw)[1].should_not.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false - Hash.ruby2_keywords_hash?(m(**kw)[1]).should == false - - m(kw).should == [[{a: 1}], {}] - m(kw)[0][0].should.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false - end - end end end end @@ -177,34 +177,16 @@ describe "A lambda literal -> () { }" do result.should == [1, 2, 3, [4, 5], 6, [7, 8], 9, 10, 11, 12] end - ruby_version_is ''...'3.0' do - evaluate <<-ruby do - @a = -> (*, **k) { k } - ruby - - @a.().should == {} - @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} - - suppress_keyword_warning do - h = mock("keyword splat") - h.should_receive(:to_hash).and_return({a: 1}) - @a.(h).should == {a: 1} - end - end - end - - ruby_version_is '3.0' do - evaluate <<-ruby do - @a = -> (*, **k) { k } - ruby - @a.().should == {} - @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} - h = mock("keyword splat") - h.should_not_receive(:to_hash) - @a.(h).should == {} - end end evaluate <<-ruby do @@ -514,34 +496,16 @@ describe "A lambda expression 'lambda { ... }'" do result.should == [1, 2, 3, [4, 5], 6, [7, 8], 9, 10, 11, 12] end - ruby_version_is ''...'3.0' do - evaluate <<-ruby do - @a = lambda { |*, **k| k } - ruby - - @a.().should == {} - @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} - - suppress_keyword_warning do - h = mock("keyword splat") - h.should_receive(:to_hash).and_return({a: 1}) - @a.(h).should == {a: 1} - end - end - end - - ruby_version_is '3.0' do - evaluate <<-ruby do - @a = lambda { |*, **k| k } - ruby - @a.().should == {} - @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} - h = mock("keyword splat") - h.should_not_receive(:to_hash) - @a.(h).should == {} - end end evaluate <<-ruby do @@ -749,68 +749,31 @@ describe "A method" do end end - ruby_version_is ""..."3.0" do - evaluate <<-ruby do - def m(a, b: 1) [a, b] end - ruby - - m(2).should == [2, 1] - m(1, b: 2).should == [1, 2] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, 1] - end - end - - evaluate <<-ruby do - def m(a, **) a end - ruby - - m(1).should == 1 - m(1, a: 2, b: 3).should == 1 - suppress_keyword_warning do - m("a" => 1, b: 2).should == {"a" => 1, b: 2} - end - end - - evaluate <<-ruby do - def m(a, **k) [a, k] end - ruby - m(1).should == [1, {}] - m(1, a: 2, b: 3).should == [1, {a: 2, b: 3}] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, {}] - end - end end - ruby_version_is "3.0" do - evaluate <<-ruby do - def m(a, b: 1) [a, b] end - ruby - - m(2).should == [2, 1] - m(1, b: 2).should == [1, 2] - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) - end - - evaluate <<-ruby do - def m(a, **) a end - ruby - m(1).should == 1 - m(1, a: 2, b: 3).should == 1 - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) - end - evaluate <<-ruby do - def m(a, **k) [a, k] end - ruby - m(1).should == [1, {}] - m(1, a: 2, b: 3).should == [1, {a: 2, b: 3}] - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) - end end evaluate <<-ruby do @@ -921,50 +884,23 @@ describe "A method" do result.should == [[1, 2, 3], 4, [5, 6], 7, [], 8] end - ruby_version_is ""..."3.0" do - evaluate <<-ruby do - def m(a=1, b:) [a, b] end - ruby - - m(b: 2).should == [1, 2] - m(2, b: 1).should == [2, 1] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [{"a" => 1}, 2] - end - end - - evaluate <<-ruby do - def m(a=1, b: 2) [a, b] end - ruby - m().should == [1, 2] - m(2).should == [2, 2] - m(b: 3).should == [1, 3] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [{"a" => 1}, 2] - end - end end - ruby_version_is "3.0" do - evaluate <<-ruby do - def m(a=1, b:) [a, b] end - ruby - - m(b: 2).should == [1, 2] - m(2, b: 1).should == [2, 1] - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) - end - - evaluate <<-ruby do - def m(a=1, b: 2) [a, b] end - ruby - m().should == [1, 2] - m(2).should == [2, 2] - m(b: 3).should == [1, 3] - -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError) - end end evaluate <<-ruby do @@ -1013,292 +949,6 @@ describe "A method" do m(1, 2, 3).should == [[1, 2], 3] end - ruby_version_is ""...'3.0' do - evaluate <<-ruby do - def m(*, a:) a end - ruby - - m(a: 1).should == 1 - m(1, 2, a: 3).should == 3 - suppress_keyword_warning do - m("a" => 1, a: 2).should == 2 - end - end - - evaluate <<-ruby do - def m(*a, b:) [a, b] end - ruby - - m(b: 1).should == [[], 1] - m(1, 2, b: 3).should == [[1, 2], 3] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [[{"a" => 1}], 2] - end - end - - evaluate <<-ruby do - def m(*, a: 1) a end - ruby - - m().should == 1 - m(1, 2).should == 1 - m(a: 2).should == 2 - m(1, a: 2).should == 2 - suppress_keyword_warning do - m("a" => 1, a: 2).should == 2 - end - end - - evaluate <<-ruby do - def m(*a, b: 1) [a, b] end - ruby - - m().should == [[], 1] - m(1, 2, 3, b: 4).should == [[1, 2, 3], 4] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [[{"a" => 1}], 2] - end - - a = mock("splat") - a.should_not_receive(:to_ary) - m(*a).should == [[a], 1] - end - - evaluate <<-ruby do - def m(*a, **) a end - ruby - - m().should == [] - m(1, 2, 3, a: 4, b: 5).should == [1, 2, 3] - m("a" => 1, a: 1).should == [] - m(1, **{a: 2}).should == [1] - - h = mock("keyword splat") - h.should_receive(:to_hash) - -> { m(**h) }.should raise_error(TypeError) - end - - evaluate <<-ruby do - def m(*, **k) k end - ruby - - m().should == {} - m(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} - m("a" => 1, a: 1).should == {"a" => 1, a: 1} - - h = mock("keyword splat") - h.should_receive(:to_hash).and_return({a: 1}) - suppress_warning do - m(h).should == {a: 1} - end - end - - evaluate <<-ruby do - def m(a = nil, **k) [a, k] end - ruby - - m().should == [nil, {}] - m("a" => 1).should == [nil, {"a" => 1}] - m(a: 1).should == [nil, {a: 1}] - m("a" => 1, a: 1).should == [nil, {"a" => 1, a: 1}] - m({ "a" => 1 }, a: 1).should == [{"a" => 1}, {a: 1}] - suppress_warning do - m({a: 1}, {}).should == [{a: 1}, {}] - - h = {"a" => 1, b: 2} - m(h).should == [{"a" => 1}, {b: 2}] - h.should == {"a" => 1, b: 2} - - h = {"a" => 1} - m(h).first.should == h - - h = {} - r = m(h) - r.first.should be_nil - r.last.should == {} - - hh = {} - h = mock("keyword splat empty hash") - h.should_receive(:to_hash).and_return(hh) - r = m(h) - r.first.should be_nil - r.last.should == {} - - h = mock("keyword splat") - h.should_receive(:to_hash).and_return({"a" => 1, a: 2}) - m(h).should == [{"a" => 1}, {a: 2}] - end - end - - evaluate <<-ruby do - def m(*a, **k) [a, k] end - ruby - - m().should == [[], {}] - m(1).should == [[1], {}] - m(a: 1, b: 2).should == [[], {a: 1, b: 2}] - m(1, 2, 3, a: 2).should == [[1, 2, 3], {a: 2}] - - m("a" => 1).should == [[], {"a" => 1}] - m(a: 1).should == [[], {a: 1}] - m("a" => 1, a: 1).should == [[], {"a" => 1, a: 1}] - m({ "a" => 1 }, a: 1).should == [[{"a" => 1}], {a: 1}] - suppress_warning do - m({a: 1}, {}).should == [[{a: 1}], {}] - end - m({a: 1}, {"a" => 1}).should == [[{a: 1}, {"a" => 1}], {}] - - bo = BasicObject.new - def bo.to_a; [1, 2, 3]; end - def bo.to_hash; {:b => 2, :c => 3}; end - - m(*bo, **bo).should == [[1, 2, 3], {:b => 2, :c => 3}] - end - - evaluate <<-ruby do - def m(*, a:) a end - ruby - - m(a: 1).should == 1 - m(1, 2, a: 3).should == 3 - suppress_keyword_warning do - m("a" => 1, a: 2).should == 2 - end - end - - evaluate <<-ruby do - def m(*a, b:) [a, b] end - ruby - - m(b: 1).should == [[], 1] - m(1, 2, b: 3).should == [[1, 2], 3] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [[{"a" => 1}], 2] - end - end - - evaluate <<-ruby do - def m(*, a: 1) a end - ruby - - m().should == 1 - m(1, 2).should == 1 - m(a: 2).should == 2 - m(1, a: 2).should == 2 - suppress_keyword_warning do - m("a" => 1, a: 2).should == 2 - end - end - - evaluate <<-ruby do - def m(*a, b: 1) [a, b] end - ruby - - m().should == [[], 1] - m(1, 2, 3, b: 4).should == [[1, 2, 3], 4] - suppress_keyword_warning do - m("a" => 1, b: 2).should == [[{"a" => 1}], 2] - end - - a = mock("splat") - a.should_not_receive(:to_ary) - m(*a).should == [[a], 1] - end - - evaluate <<-ruby do - def m(*a, **) a end - ruby - - m().should == [] - m(1, 2, 3, a: 4, b: 5).should == [1, 2, 3] - m("a" => 1, a: 1).should == [] - m(1, **{a: 2}).should == [1] - - h = mock("keyword splat") - h.should_receive(:to_hash) - -> { m(**h) }.should raise_error(TypeError) - end - - evaluate <<-ruby do - def m(*, **k) k end - ruby - - m().should == {} - m(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5} - m("a" => 1, a: 1).should == {"a" => 1, a: 1} - - h = mock("keyword splat") - h.should_receive(:to_hash).and_return({a: 1}) - suppress_keyword_warning do - m(h).should == {a: 1} - end - end - - evaluate <<-ruby do - def m(a = nil, **k) [a, k] end - ruby - - m().should == [nil, {}] - m("a" => 1).should == [nil, {"a" => 1}] - m(a: 1).should == [nil, {a: 1}] - m("a" => 1, a: 1).should == [nil, {"a" => 1, a: 1}] - m({ "a" => 1 }, a: 1).should == [{"a" => 1}, {a: 1}] - suppress_keyword_warning do - m({a: 1}, {}).should == [{a: 1}, {}] - end - - h = {"a" => 1, b: 2} - suppress_keyword_warning do - m(h).should == [{"a" => 1}, {b: 2}] - end - h.should == {"a" => 1, b: 2} - - h = {"a" => 1} - m(h).first.should == h - - h = {} - suppress_keyword_warning do - m(h).should == [nil, {}] - end - - hh = {} - h = mock("keyword splat empty hash") - h.should_receive(:to_hash).and_return({a: 1}) - suppress_keyword_warning do - m(h).should == [nil, {a: 1}] - end - - h = mock("keyword splat") - h.should_receive(:to_hash).and_return({"a" => 1}) - m(h).should == [h, {}] - end - - evaluate <<-ruby do - def m(*a, **k) [a, k] end - ruby - - m().should == [[], {}] - m(1).should == [[1], {}] - m(a: 1, b: 2).should == [[], {a: 1, b: 2}] - m(1, 2, 3, a: 2).should == [[1, 2, 3], {a: 2}] - - m("a" => 1).should == [[], {"a" => 1}] - m(a: 1).should == [[], {a: 1}] - m("a" => 1, a: 1).should == [[], {"a" => 1, a: 1}] - m({ "a" => 1 }, a: 1).should == [[{"a" => 1}], {a: 1}] - suppress_keyword_warning do - m({a: 1}, {}).should == [[{a: 1}], {}] - end - m({a: 1}, {"a" => 1}).should == [[{a: 1}, {"a" => 1}], {}] - - bo = BasicObject.new - def bo.to_a; [1, 2, 3]; end - def bo.to_hash; {:b => 2, :c => 3}; end - - m(*bo, **bo).should == [[1, 2, 3], {:b => 2, :c => 3}] - end - end - evaluate <<-ruby do def m(*, &b) b end ruby @@ -1462,42 +1112,20 @@ describe "A method" do -> { m("a" => 1) }.should raise_error(ArgumentError) end - ruby_version_is ''...'3.0' do - evaluate <<-ruby do - def m(a, b = nil, c = nil, d, e: nil, **f) - [a, b, c, d, e, f] - end - ruby - - result = m(1, 2) - result.should == [1, nil, nil, 2, nil, {}] - - suppress_warning do - result = m(1, 2, {foo: :bar}) - result.should == [1, nil, nil, 2, nil, {foo: :bar}] end - result = m(1, {foo: :bar}) - result.should == [1, nil, nil, {foo: :bar}, nil, {}] - end - end - - ruby_version_is '3.0' do - evaluate <<-ruby do - def m(a, b = nil, c = nil, d, e: nil, **f) - [a, b, c, d, e, f] - end - ruby - - result = m(1, 2) - result.should == [1, nil, nil, 2, nil, {}] - result = m(1, 2, {foo: :bar}) - result.should == [1, 2, nil, {foo: :bar}, nil, {}] - result = m(1, {foo: :bar}) - result.should == [1, nil, nil, {foo: :bar}, nil, {}] - end end end @@ -1511,60 +1139,27 @@ describe "A method" do end end - ruby_version_is ''...'3.0' do - context 'when passing an empty keyword splat to a method that does not accept keywords' do - evaluate <<-ruby do - def m(a); a; end - ruby - h = {} - - -> do - m(**h).should == {} - end.should complain(/warning: Passing the keyword argument as the last hash parameter is deprecated/) - end - end - end - - ruby_version_is ''...'3.0' do - context "assigns keyword arguments from a passed Hash without modifying it" do - evaluate <<-ruby do - def m(a: nil); a; end - ruby - options = {a: 1}.freeze - -> do - suppress_warning do - m(options).should == 1 - end - end.should_not raise_error - options.should == {a: 1} - end end end - ruby_version_is '3.0' do - context 'when passing an empty keyword splat to a method that does not accept keywords' do - evaluate <<-ruby do - def m(a); a; end - ruby - h = {} - - -> do - m(**h).should == {} - end.should raise_error(ArgumentError) - end - end - - context "raises ArgumentError if passing hash as keyword arguments" do - evaluate <<-ruby do - def m(a: nil); a; end - ruby - options = {a: 1}.freeze - -> do - m(options) - end.should raise_error(ArgumentError) - end end end @@ -1670,105 +1265,107 @@ describe "An array-dereference method ([])" do end end -ruby_version_is "3.0" do - describe "An endless method definition" do - context "without arguments" do - evaluate <<-ruby do - def m() = 42 - ruby - - m.should == 42 - end - - context "without parenthesis" do - evaluate <<-ruby do - def m = 42 - ruby - m.should == 42 - end - end end - context "with arguments" do evaluate <<-ruby do - def m(a, b) = a + b - ruby - m(1, 4).should == 5 end end - context "with multiline body" do - evaluate <<-ruby do - def m(n) = - if n > 2 - m(n - 2) + m(n - 1) - else - 1 - end - ruby - m(6).should == 8 - end end - context "with args forwarding" do - evaluate <<-ruby do - def mm(word, num:) - word * num end - def m(...) = mm(...) + mm(...) - ruby - - m("meow", num: 2).should == "meow" * 4 - end end - ruby_version_is ""..."3.0" do - context "inside 'endless' method definitions" do - it "does not allow method calls without parenthesis" do - -> { - eval("def greet(person) = 'Hi, '.concat person") - }.should raise_error(SyntaxError) end - end end end - describe "Keyword arguments are now separated from positional arguments" do - context "when the method has only positional parameters" do - it "treats incoming keyword arguments as positional for compatibility" do - def foo(a, b, c, hsh) - hsh[:key] - end - - foo(1, 2, 3, key: 42).should == 42 end end - context "when the method takes a ** parameter" do - it "captures the passed literal keyword arguments" do - def foo(a, b, c, **hsh) - hsh[:key] - end - foo(1, 2, 3, key: 42).should == 42 end - it "captures the passed ** keyword arguments" do - def foo(a, b, c, **hsh) - hsh[:key] - end - h = { key: 42 } - foo(1, 2, 3, **h).should == 42 end - it "does not convert a positional Hash to keyword arguments" do - def foo(a, b, c, **hsh) - hsh[:key] end -> { @@ -1777,28 +1374,14 @@ ruby_version_is "3.0" do end end - context "when the method takes a key: parameter" do - context "when it's called with a positional Hash and no **" do - it "raises ArgumentError" do - def foo(a, b, c, key: 1) - key - end - - -> { - foo(1, 2, 3, { key: 42 }) - }.should raise_error(ArgumentError, 'wrong number of arguments (given 4, expected 3)') end - end - - context "when it's called with **" do - it "captures the passed keyword arguments" do - def foo(a, b, c, key: 1) - key - end - h = { key: 42 } - foo(1, 2, 3, **h).should == 42 - end end end end @@ -78,20 +78,10 @@ describe "Assigning an anonymous module to a constant" do mod.name.should == "ModuleSpecs_CS1" end - ruby_version_is ""..."3.0" do - it "does not set the name of a module scoped by an anonymous module" do - a, b = Module.new, Module.new - a::B = b - b.name.should be_nil - end - end - - ruby_version_is "3.0" do - it "sets the name of a module scoped by an anonymous module" do - a, b = Module.new, Module.new - a::B = b - b.name.should.end_with? '::B' - end end it "sets the name of contained modules when assigning a toplevel anonymous module" do @@ -31,38 +31,19 @@ describe "Numbered parameters" do }.should raise_error(SyntaxError, /numbered parameter is already used in/m) end - ruby_version_is ''...'3.0' do - it "can be overwritten with local variable" do - suppress_warning do - eval <<~CODE - _1 = 0 - proc { _1 }.call("a").should == 0 - CODE - end - end - - it "warns when numbered parameter is overwritten with local variable" do - -> { - eval("_1 = 0") - }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/) - end end - ruby_version_is '3.0' do - it "cannot be overwritten with local variable" do - -> { - eval <<~CODE - _1 = 0 - proc { _1 }.call("a").should == 0 - CODE - }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/) - end - - it "errors when numbered parameter is overwritten with local variable" do - -> { - eval("_1 = 0") - }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/) - end end it "raises SyntaxError when block parameters are specified explicitly" do @@ -80,16 +61,8 @@ describe "Numbered parameters" do end describe "assigning to a numbered parameter" do - ruby_version_is ''...'3.0' do - it "warns" do - -> { eval("proc { _1 = 0 }") }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/) - end - end - - ruby_version_is '3.0' do - it "raises SyntaxError" do - -> { eval("proc { _1 = 0 }") }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/) - end end end @@ -8,115 +8,113 @@ describe "Pattern matching" do ScratchPad.record [] end - ruby_version_is "3.0" do - it "can be standalone assoc operator that deconstructs value" do - suppress_warning do - eval(<<-RUBY).should == [0, 1] - [0, 1] => [a, b] - [a, b] - RUBY - end end - describe "find pattern" do - it "captures preceding elements to the pattern" do - eval(<<~RUBY).should == [0, 1] - case [0, 1, 2, 3] - in [*pre, 2, 3] - pre - else - false - end - RUBY - end - it "captures following elements to the pattern" do - eval(<<~RUBY).should == [2, 3] - case [0, 1, 2, 3] - in [0, 1, *post] - post - else - false - end - RUBY - end - it "captures both preceding and following elements to the pattern" do - eval(<<~RUBY).should == [[0, 1], [3, 4]] - case [0, 1, 2, 3, 4] - in [*pre, 2, *post] - [pre, post] - else - false - end - RUBY - end - it "can capture the entirety of the pattern" do - eval(<<~RUBY).should == [0, 1, 2, 3, 4] - case [0, 1, 2, 3, 4] - in [*everything] - everything - else - false - end - RUBY - end - it "will match an empty Array-like structure" do - eval(<<~RUBY).should == [] - case [] - in [*everything] - everything - else - false - end - RUBY - end - it "can be nested" do - eval(<<~RUBY).should == [[0, [2, 4, 6]], [[4, 16, 64]], 27] - case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]] - in [*pre, [*, 9, a], *post] - [pre, post, a] - else - false - end - RUBY - end - it "can be nested with an array pattern" do - eval(<<~RUBY).should == [[4, 16, 64]] - case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]] - in [_, _, [*, 9, *], *post] - post - else - false - end - RUBY - end - it "can be nested within a hash pattern" do - eval(<<~RUBY).should == [27] - case {a: [3, 9, 27]} - in {a: [*, 9, *post]} - post - else - false - end - RUBY - end - it "can nest hash and array patterns" do - eval(<<~RUBY).should == [42, 2] - case [0, {a: 42, b: [0, 1]}, {a: 42, b: [1, 2]}] - in [*, {a:, b: [1, c]}, *] - [a, c] - else - false - end - RUBY - end end end @@ -154,35 +152,25 @@ describe "Pattern matching" do @src = 'case [0, 1]; in [a, b]; end' end - ruby_version_is ""..."3.0" do - it "warns about pattern matching is experimental feature" do - -> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i) - end - end - - ruby_version_is "3.0" do - it "does not warn about pattern matching is experimental feature" do - -> { eval @src }.should_not complain - end end end context 'when one-line form' do - ruby_version_is '3.0' do - before :each do - @src = '[0, 1] => [a, b]' - end - ruby_version_is ""..."3.1" do - it "warns about pattern matching is experimental feature" do - -> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i) - end end - ruby_version_is "3.1" do - it "does not warn about pattern matching is experimental feature" do - -> { eval @src }.should_not complain - end end end end @@ -687,26 +675,24 @@ describe "Pattern matching" do RUBY end - ruby_version_is "3.0" do - it "calls #deconstruct once for multiple patterns, caching the result" do - obj = Object.new - def obj.deconstruct - ScratchPad << :deconstruct - [0, 1] - end - eval(<<~RUBY).should == true - case obj - in [1, 2] - false - in [0, 1] - true - end - RUBY - ScratchPad.recorded.should == [:deconstruct] - end end it "calls #deconstruct even on objects that are already an array" do @@ -1161,47 +1161,20 @@ end describe "The predefined global constants" do describe "TRUE" do - ruby_version_is "3.0" do - it "is no longer defined" do - Object.const_defined?(:TRUE).should == false - end - end - - ruby_version_is ""..."3.0" do - it "includes TRUE" do - Object.const_defined?(:TRUE).should == true - -> { TRUE }.should complain(/constant ::TRUE is deprecated/) - end end end describe "FALSE" do - ruby_version_is "3.0" do - it "is no longer defined" do - Object.const_defined?(:FALSE).should == false - end - end - - ruby_version_is ""..."3.0" do - it "includes FALSE" do - Object.const_defined?(:FALSE).should == true - -> { FALSE }.should complain(/constant ::FALSE is deprecated/) - end end end describe "NIL" do - ruby_version_is "3.0" do - it "is no longer defined" do - Object.const_defined?(:NIL).should == false - end - end - - ruby_version_is ""..."3.0" do - it "includes NIL" do - Object.const_defined?(:NIL).should == true - -> { NIL }.should complain(/constant ::NIL is deprecated/) - end end end @@ -235,18 +235,8 @@ describe "A Proc" do @p = proc { |*a, **kw| [a, kw] } end - ruby_version_is ""..."3.0" do - it 'autosplats keyword arguments and warns' do - -> { - @p.call([1, {a: 1}]).should == [[1], {a: 1}] - }.should complain(/warning: Using the last argument as keyword parameters is deprecated; maybe \*\* should be added to the call/) - end - end - - ruby_version_is "3.0" do - it 'does not autosplat keyword arguments' do - @p.call([1, {a: 1}]).should == [[[1, {a: 1}]], {}] - end end end @@ -614,10 +614,8 @@ describe "Regexp with character classes" do "1".match(eval("/\P{N}/")).should be_nil end - ruby_bug "#17340", ''...'3.0' do - it "raises a RegexpError for an unterminated unicode property" do - -> { Regexp.new('\p{') }.should raise_error(RegexpError) - end end it "supports \\X (unicode 9.0 with UTR #51 workarounds)" do @@ -87,9 +87,7 @@ describe "Regexps with repetition" do /a+?*/.match("a")[0].should == "a" /(a+?)*/.match("a")[0].should == "a" - ruby_bug '#17341', ''...'3.0' do - /a+?*/.match("aa")[0].should == "aa" - end /(a+?)*/.match("aa")[0].should == "aa" # a+?+ should not be reduced, it should be equivalent to (a+?)+ @@ -100,9 +98,7 @@ describe "Regexps with repetition" do /a+?+/.match("a")[0].should == "a" /(a+?)+/.match("a")[0].should == "a" - ruby_bug '#17341', ''...'3.0' do - /a+?+/.match("aa")[0].should == "aa" - end /(a+?)+/.match("aa")[0].should == "aa" # both a**? and a+*? should be equivalent to (a+)?? @@ -18,10 +18,8 @@ describe "Literal Regexps" do /Hello/.should be_kind_of(Regexp) end - ruby_version_is "3.0" do - it "is frozen" do - /Hello/.should.frozen? - end end it "caches the Regexp object" do @@ -1,27 +1,11 @@ require_relative '../spec_helper' describe "The $SAFE variable" do - ruby_version_is ""..."3.0" do - it "warn when access" do - -> { - $SAFE - }.should complain(/\$SAFE will become a normal global variable in Ruby 3.0/) - end - - it "warn when set" do - -> { - $SAFE = 1 - }.should complain(/\$SAFE will become a normal global variable in Ruby 3.0/) - end - end - - ruby_version_is "3.0" do - it "$SAFE is a regular global variable" do - $SAFE.should == nil - $SAFE = 42 - $SAFE.should == 42 - ensure - $SAFE = nil - end end end @@ -411,36 +411,18 @@ describe "Invoking a method" do specs.rest_len(0,*a,4,*5,6,7,*c,-1).should == 11 end - ruby_version_is ""..."3.0" do - it "expands the Array elements from the splat after executing the arguments and block if no other arguments follow the splat" do - def self.m(*args, &block) - [args, block] - end - - args = [1, nil] - m(*args, &args.pop).should == [[1], nil] - - args = [1, nil] - order = [] - m(*(order << :args; args), &(order << :block; args.pop)).should == [[1], nil] - order.should == [:args, :block] end - end - ruby_version_is "3.0" do - it "expands the Array elements from the splat before applying block argument operations" do - def self.m(*args, &block) - [args, block] - end - - args = [1, nil] - m(*args, &args.pop).should == [[1, nil], nil] - args = [1, nil] - order = [] - m(*(order << :args; args), &(order << :block; args.pop)).should == [[1, nil], nil] - order.should == [:args, :block] - end end it "evaluates the splatted arguments before the block if there are other arguments after the splat" do @@ -277,23 +277,11 @@ describe "Ruby String interpolation" do eval(code).should_not.frozen? end - ruby_version_is "3.0" do - it "creates a non-frozen String when # frozen-string-literal: true is used" do - code = <<~'RUBY' - # frozen-string-literal: true - "a#{6*7}c" - RUBY - eval(code).should_not.frozen? - end - end - - ruby_version_is ""..."3.0" do - it "creates a frozen String when # frozen-string-literal: true is used" do - code = <<~'RUBY' - # frozen-string-literal: true - "a#{6*7}c" - RUBY - eval(code).should.frozen? - end end end @@ -904,22 +904,11 @@ end describe "Instance variables" do context "when instance variable is uninitialized" do - ruby_version_is ""..."3.0" do - it "warns about accessing uninitialized instance variable" do - obj = Object.new - def obj.foobar; a = @a; end - - -> { obj.foobar }.should complain(/warning: instance variable @a not initialized/, verbose: true) - end - end - - ruby_version_is "3.0" do - it "doesn't warn about accessing uninitialized instance variable" do - obj = Object.new - def obj.foobar; a = @a; end - -> { obj.foobar }.should_not complain(verbose: true) - end end it "doesn't warn at lazy initialization" do @@ -186,31 +186,14 @@ describe "The yield call" do end describe "Using yield in a singleton class literal" do - ruby_version_is ""..."3.0" do - it 'emits a deprecation warning' do - code = <<~RUBY - def m - class << Object.new - yield - end - end - m { :ok } - RUBY - - -> { eval(code) }.should complain(/warning: `yield' in class syntax will not be supported from Ruby 3.0/) - end - end - - ruby_version_is "3.0" do - it 'raises a SyntaxError' do - code = <<~RUBY - class << Object.new - yield - end - RUBY - -> { eval(code) }.should raise_error(SyntaxError, /Invalid yield/) - end end end |