8000 Start handling `&nil` in method parameters · ruby/ruby@67487ef · GitHub
[go: up one dir, main page]

Sk 8000 ip to content

Commit 67487ef

Browse files
committed
Start handling &nil in method parameters
Similar to `:nokey` for `**nil` declaring methods/procs, a method/proc with a `&nil` declaration will return a `:noblock` entry in the parameters array.
1 parent 75fba09 commit 67487ef

File tree

6 files changed

+52
-1
lines changed

6 files changed

+52
-1
lines changed

iseq.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3586,7 +3586,13 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
35863586
}
35873587
rb_ary_push(args, a);
35883588
}
3589-
if (body->param.flags.has_block) {
3589+
if (body->param.flags.accepts_no_block) {
3590+
ID noblock;
3591+
CONST_ID(noblock, "noblock");
3592+
PARAM_TYPE(noblock);
3593+
rb_ary_push(args, a);
3594+
}
3595+
else if (body->param.flags.has_block) {
35903596
CONST_ID(block, "block");
35913597
rb_ary_push(args, PARAM(body->param.block_start, block));
35923598
}

proc.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3177,6 +3177,7 @@ method_inspect(VALUE method)
31773177
const VALUE keyrest = ID2SYM(rb_intern("keyrest"));
31783178
const VALUE block = ID2SYM(rb_intern("block"));
31793179
const VALUE nokey = ID2SYM(rb_intern("nokey"));
3180+
const VALUE noblock = ID2SYM(rb_intern("noblock"));
31803181
int forwarding = 0;
31813182

31823183
rb_str_buf_cat2(str, "(");
@@ -3210,6 +3211,9 @@ method_inspect(VALUE method)
32103211
else if (kind == nokey) {
32113212
name = rb_str_new2("nil");
32123213
}
3214+
else if (kind == noblock) {
3215+
name = rb_str_new2("nil");
3216+
}
32133217
}
32143218

32153219
if (kind == req) {
@@ -3259,6 +3263,9 @@ method_inspect(VALUE method)
32593263
else if (kind == nokey) {
32603264
rb_str_buf_cat2(str, "**nil");
32613265
}
3266+
else if (kind == noblock) {
3267+
rb_str_buf_cat2(str, "&nil");
3268+
}
32623269

32633270
if (i < RARRAY_LEN(params) - 1) {
32643271
rb_str_buf_cat2(str, ", ");

spec/ruby/core/method/parameters_spec.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ def one_splat_one_block(*args, &block)
2222
local_is_not_parameter = {}
2323
end
2424

25+
ruby_version_is "3.4" do
26+
eval <<-RUBY
27+
def one_noblock(&nil); end
28+
RUBY
29+
end
30+
2531
def forward_parameters(...) end
2632

2733
def underscore_parameters(_, _, _ = 1, *_, _:, _: 2, **_, &_); end
@@ -187,6 +193,13 @@ def underscore_parameters(_, _, _ = 1, *_, _:, _: 2, **_, &_); end
187193
m.parameters.should == [[:nokey]]
188194
end
189195

196+
ruby_version_is "3.4" do
197+
it "returns [[:noblock]] for a method with a single &nil parameter" do
198+
m = MethodSpecs::Methods.instance_method(:one_noblock)
199+
m.parameters.should == [[:noblock]]
200+
end
201+
end
202+
190203
it "works with ->(){} as the value of an optional argument" do
191204
m = MethodSpecs::Methods.instance_method(:one_opt_with_stabby)
192205
m.parameters.should == [[:opt,:a]]

spec/ruby/core/proc/parameters_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,12 @@
174174
it "returns :nokey for **nil parameter" do
175175
proc { |**nil| }.parameters.should == [[:nokey]]
176176
end
177+
178+
ruby_version_is "3.4" do
179+
it "returns :noblock for &nil parameter" do
180+
eval <<~RUBY
181+
proc { |&nil| }.parameters.should == [[:noblock]]
182+
RUBY
183+
end
184+
end
177185
end

test/ruby/test_iseq.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,17 @@ def foo(**nil); end
633633
assert_equal([[:nokey]], iseq.eval.singleton_method(:foo).parameters)
634634
end
635635

636+
def test_to_binary_dumps_noblock
637+
iseq = assert_iseq_to_binary(<<-RUBY)
638+
o = Object.new
639+
class << o
640+
def foo(&nil); end
641+
end
642+
o
643+
RUBY
644+
assert_equal([[:noblock]], iseq.eval.singleton_method(:foo).parameters)
645+
end
646+
636647
def test_to_binary_line_info
637648
assert_iseq_to_binary("#{<<~"begin;"}\n#{<<~'end;'}", '[Bug #14660]').eval
638649
begin;

test/ruby/test_method.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def mk6(a, b = nil, c, **o) nil && o end
3232
def mk7(a, b = nil, *c, d, **o) nil && o end
3333
def mk8(a, b = nil, *c, d, e:, f: nil, **o) nil && o end
3434
def mnk(**nil) end
35+
def mnb(&nil) end
3536
def mf(...) end
3637

3738
class Base
@@ -577,6 +578,7 @@ def obj.respond_to_missing?(id, *)
577578
define_method(:pmk7) {|a, b = nil, *c, d, **o|}
578579
define_method(:pmk8) {|a, b = nil, *c, d, e:, f: nil, **o|}
579580
define_method(:pmnk) {|**nil|}
581+
define_method(:pmnb) {|&nil|}
580582

581583
def test_bound_parameters
582584
assert_equal([], method(:m0).parameters)
@@ -600,6 +602,7 @@ def test_bound_parameters
600602
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], method(:mk7).parameters)
601603
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], method(:mk8).parameters)
602604
assert_equal([[:nokey]], method(:mnk).parameters)
605+
assert_equal([[:noblock]], method(:mnb).parameters)
603606
# pending
604607
assert_equal([[:rest, :*], [:keyrest, :**], [:block, :&]], method(:mf).parameters)
605608
end
@@ -626,6 +629,7 @@ def test_unbound_parameters
626629
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], self.class.instance_method(:mk7).parameters)
627630
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], self.class.instance_method(:mk8).parameters)
628631
assert_equal([[:nokey]], self.class.instance_method(:mnk).parameters)
632+
assert_equal([[:noblock]], self.class.instance_method(:mnb).parameters)
629633
# pending
630634
assert_equal([[:rest, :*], [:keyrest, :**], [:block, :&]], self.class.instance_method(:mf).parameters)
631635
end
@@ -651,6 +655,7 @@ def test_bmethod_bound_parameters
651655
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], method(:pmk7).parameters)
652656
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], method(:pmk8).parameters)
653657
assert_equal([[:nokey]], method(:pmnk).parameters)
658+
assert_equal([[:noblock]], method(:pmnb).parameters)
654659
end
655660

656661
def test_bmethod_unbound_parameters
@@ -675,6 +680,7 @@ def test_bmethod_unbound_parameters
675680
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], self.class.instance_method(:pmk7).parameters)
676681
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], self.class.instance_method(:pmk8).parameters)
677682
assert_equal([[:nokey]], self.class.instance_method(:pmnk).parameters)
683+
assert_equal([[:noblock]], self.class.instance_method(:pmnb).parameters)
678684
end
679685

680686
def test_hidden_parameters

0 commit comments

Comments
 (0)
0