From: josh.cheek@... Date: 2021-06-29T06:09:12+00:00 Subject: [ruby-core:104432] [Ruby master Bug#18011] `Method#parameters` is incorrect for forwarded arguments Issue #18011 has been updated by josh.cheek (Josh Cheek). jeremyevans0 (Jeremy Evans) wrote in #note-1: > Forwarded arguments is implemented as `(*args, &block)` with `ruby2_keywords`, not as `(*args, **kwargs, &block)`. If you add `def wrapper4(*r, &b) = wrapped(*r, &b),` to `methods` and then `ruby2_keywords :wrapper4` after `methods`, you can see it gives the same output as `wrapper1` and `wrapper3`. > > If we want to indicate which methods have `ruby2_keywords`, one way would be to include `ruby2_keywords` into `Method#parameters` output if it is enabled for the method. Possibly this could be done by adding `[:ruby2_keywords]` as the last value in the returned array. Thanks for the reply, I didn't know about the `ruby2_keywords` method. I guess if the people here disagree with me, then they can close this issue. I guess I can detect this by the argument names of `:*` and `:&`, there doesn't seem to be any other way to get that. --- For reference to any readers, he's saying to add another example like this: ```ruby def wrapped(ord, kw:) = [ord, {kw: kw}] methods = [ # ... def wrapper4(*r, &b) = wrapped(*r, &b), ] ruby2_keywords :wrapper4 methods.each do |name| # ... end ``` Output: ``` # ... wrapper4(*r, &b) params: [[:rest, :r], [:block, :b]] result: [123, {:kw=>456}] ``` --- Maybe worth noting that Ripper also parses it into the rest arg: ``` ruby -vr ripper -e ' def args_for(sig) = %i(req opt rest req key keyrest block).zip(Ripper.sexp(sig)[1][0][2][1][1..]) pp args_for "def m(...) end" pp args_for "def m(*, **) end" ' ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [arm64-darwin20] [[:req, nil], [:opt, nil], [:rest, [:args_forward]], [:req, nil], [:key, nil], [:keyrest, nil], [:block, nil]] [[:req, nil], [:opt, nil], [:rest, [:rest_param, nil]], [:req, nil], [:key, nil], [:keyrest, [:kwrest_param, nil]], [:block, nil]] ``` ---------------------------------------- Bug #18011: `Method#parameters` is incorrect for forwarded arguments https://bugs.ruby-lang.org/issues/18011#change-92686 * Author: josh.cheek (Josh Cheek) * Status: Open * Priority: Normal * ruby -v: ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [arm64-darwin20] * Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN ---------------------------------------- When asking a method about its parameters, forwarded arguments say they are a rest and a block (`wrapper1` in the example below). However, when we use that signature, it raises an ArgumentError (`wrapper2` in the example below). When I add a keyrest to the signature, it works as expected (`wrapper3` in the example below). So I think forwarded arguments should include a keyrest in the output of `Method#parameters` ```ruby def wrapped(ord, kw:) = [ord, {kw: kw}] methods = [ def wrapper1(...) = wrapped(...), def wrapper2(*r, &b) = wrapped(*r, &b), def wrapper3(*r, **k, &b) = wrapped(*r, **k, &b), ] methods.each do |name| puts File.read(__FILE__)[/#{name}\(.*?\)/] puts " params: #{method(name).parameters.inspect}" puts " result: #{(method(name).call 123, kw: 456 rescue $!).inspect}" puts end ``` Output: ``` wrapper1(...) params: [[:rest, :*], [:block, :&]] result: [123, {:kw=>456}] wrapper2(*r, &b) params: [[:rest, :r], [:block, :b]] result: # wrapper3(*r, **k, &b) params: [[:rest, :r], [:keyrest, :k], [:block, :b]] result: [123, {:kw=>456}] ``` -- https://bugs.ruby-lang.org/ Unsubscribe: