mruby-proc-ext: Proc#curry should check max arity for lambdas

`lambda {|a, b=nil|}.curry(3)` used to silently return a curried Proc;
CRuby raises `ArgumentError` because the lambda accepts at most 2 args.
Use `self.parameters` to compute the upper bound (count `:req`/`:opt`
entries, unbounded if `:rest`/`:keyrest` is present) and add the
corresponding range check alongside the existing minimum check.

close #2855

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-05-11 14:06:28 +09:00
parent 46151db893
commit 3fc7dd1858
2 changed files with 23 additions and 3 deletions
+16 -3
View File
@@ -75,9 +75,22 @@ class Proc
if lambda?
type = :lambda
self_arity = self.arity
if (self_arity >= 0 && arity != self_arity) ||
(self_arity < 0 && abs[self_arity] > arity)
raise ArgumentError, "wrong number of arguments (given #{arity}, expected #{abs[self_arity]})"
min_req = abs[self_arity]
if self_arity < 0
max_arity = 0
has_rest = false
self.parameters.each do |p|
case p[0]
when :rest, :keyrest then has_rest = true
when :req, :opt then max_arity += 1
end
end
if arity < min_req || (!has_rest && arity > max_arity)
expected = (!has_rest && max_arity != min_req) ? "#{min_req}..#{max_arity}" : min_req.to_s
raise ArgumentError, "wrong number of arguments (given #{arity}, expected #{expected})"
end
elsif arity != self_arity
raise ArgumentError, "wrong number of arguments (given #{arity}, expected #{self_arity})"
end
end
+7
View File
@@ -64,6 +64,13 @@ assert('Proc#curry') do
assert_false(proc{}.curry.lambda?)
assert_true(lambda{}.curry.lambda?)
# #2855: lambda with optional param: curry must validate against max arity
l = lambda {|a, b=nil|}
assert_raise(ArgumentError) { l.curry(3) } # over max
assert_kind_of Proc, l.curry(2) # within range
assert_kind_of Proc, l.curry(1) # at min
assert_kind_of Proc, lambda {|a, *b|}.curry(99) # rest -> unbounded
end
assert('Proc#parameters') do