Skip to content

Commit 3effc7b

Browse files
committed
Add specs for SyntaxError when rest/kwrest and block parameters are forwarded within a block
Now in Ruby 3.3 anonymous parameters forwarding is disallowed inside a block that uses anonymous parameters. [Feature #19370]
1 parent 8e0b9e5 commit 3effc7b

File tree

3 files changed

+83
-11
lines changed

3 files changed

+83
-11
lines changed

language/block_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,7 @@ def a; 1; end
999999
end
10001000
end
10011001

1002+
# tested more thoroughly in language/delegation_spec.rb
10021003
describe "Anonymous block forwarding" do
10031004
ruby_version_is "3.1" do
10041005
it "forwards blocks to other method that formally declares anonymous block" do

language/delegation_spec.rb

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require_relative '../spec_helper'
22
require_relative 'fixtures/delegation'
33

4+
# Forwarding anonymous parameters
45
describe "delegation with def(...)" do
56
it "delegates rest and kwargs" do
67
a = Class.new(DelegationSpecs::Target)
@@ -10,10 +11,10 @@ def delegate(...)
1011
end
1112
RUBY
1213

13-
a.new.delegate(1, b: 2).should == [[1], {b: 2}]
14+
a.new.delegate(1, b: 2).should == [[1], {b: 2}, nil]
1415
end
1516

16-
it "delegates block" do
17+
it "delegates a block literal" do
1718
a = Class.new(DelegationSpecs::Target)
1819
a.class_eval(<<-RUBY)
1920
def delegate_block(...)
@@ -24,6 +25,18 @@ def delegate_block(...)
2425
a.new.delegate_block(1, b: 2) { |x| x }.should == [{b: 2}, [1]]
2526
end
2627

28+
it "delegates a block argument" do
29+
a = Class.new(DelegationSpecs::Target)
30+
a.class_eval(<<-RUBY)
31+
def delegate(...)
32+
target(...)
33+
end
34+
RUBY
35+
36+
block = proc {}
37+
a.new.delegate(1, b: 2, &block).should == [[1], {b: 2}, block]
38+
end
39+
2740
it "parses as open endless Range when brackets are omitted" do
2841
a = Class.new(DelegationSpecs::Target)
2942
suppress_warning do
@@ -34,7 +47,7 @@ def delegate(...)
3447
RUBY
3548
end
3649

37-
a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true)
50+
a.new.delegate(1, b: 2).should == Range.new([[], {}, nil], nil, true)
3851
end
3952
end
4053

@@ -47,10 +60,10 @@ def delegate(x, ...)
4760
end
4861
RUBY
4962

50-
a.new.delegate(0, 1, b: 2).should == [[1], {b: 2}]
63+
a.new.delegate(0, 1, b: 2).should == [[1], {b: 2}, nil]
5164
end
5265

53-
it "delegates block" do
66+
it "delegates a block literal" do
5467
a = Class.new(DelegationSpecs::Target)
5568
a.class_eval(<<-RUBY)
5669
def delegate_block(x, ...)
@@ -60,6 +73,18 @@ def delegate_block(x, ...)
6073

6174
a.new.delegate_block(0, 1, b: 2) { |x| x }.should == [{b: 2}, [1]]
6275
end
76+
77+
it "delegates a block argument" do
78+
a = Class.new(DelegationSpecs::Target)
79+
a.class_eval(<<-RUBY)
80+
def delegate(...)
81+
target(...)
82+
end
83+
RUBY
84+
85+
block = proc {}
86+
a.new.delegate(1, b: 2, &block).should == [[1], {b: 2}, block]
87+
end
6388
end
6489

6590
ruby_version_is "3.2" do
@@ -70,9 +95,19 @@ def delegate_block(x, ...)
7095
def delegate(*)
7196
target(*)
7297
end
73-
RUBY
98+
RUBY
7499

75-
a.new.delegate(0, 1).should == [[0, 1], {}]
100+
a.new.delegate(0, 1).should == [[0, 1], {}, nil]
101+
end
102+
103+
ruby_version_is "3.3" do
104+
context "within a block that accepts anonymous rest within a method that accepts anonymous rest" do
105+
it "does not allow delegating rest" do
106+
-> {
107+
eval "def m(*); proc { |*| n(*) } end"
108+
}.should raise_error(SyntaxError, /anonymous rest parameter is also used within block/)
109+
end
110+
end
76111
end
77112
end
78113
end
@@ -85,9 +120,45 @@ def delegate(*)
85120
def delegate(**)
86121
target(**)
87122
end
88-
RUBY
123+
RUBY
124+
125+
a.new.delegate(a: 1) { |x| x }.should == [[], {a: 1}, nil]
126+
end
89127

90-
a.new.delegate(a: 1) { |x| x }.should == [[], {a: 1}]
128+
ruby_version_is "3.3" do
129+
context "within a block that accepts anonymous kwargs within a method that accepts anonymous kwargs" do
130+
it "does not allow delegating kwargs" do
131+
-> {
132+
eval "def m(**); proc { |**| n(**) } end"
133+
}.should raise_error(SyntaxError, /anonymous keyword rest parameter is also used within block/)
134+
end
135+
end
136+
end
137+
end
138+
end
139+
140+
ruby_version_is "3.1" do
141+
describe "delegation with def(&)" do
142+
it "delegates an anonymous block parameter" do
143+
a = Class.new(DelegationSpecs::Target)
144+
a.class_eval(<<-RUBY)
145+
def delegate(&)
146+
target(&)
147+
end
148+
RUBY
149+
150+
block = proc {}
151+
a.new.delegate(&block).should == [[], {}, block]
152+
end
153+
154+
ruby_version_is "3.3" do
155+
context "within a block that accepts anonymous block within a method that accepts anonymous block" do
156+
it "does not allow delegating a block" do
157+
-> {
158+
eval "def m(&); proc { |&| n(&) } end"
159+
}.should raise_error(SyntaxError, /anonymous block parameter is also used within block/)
160+
end
161+
end
91162
end
92163
end
93164
end

language/fixtures/delegation.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module DelegationSpecs
22
class Target
3-
def target(*args, **kwargs)
4-
[args, kwargs]
3+
def target(*args, **kwargs, &block)
4+
[args, kwargs, block]
55
end
66

77
def target_block(*args, **kwargs)

0 commit comments

Comments
 (0)