rspec-support icon indicating copy to clipboard operation
rspec-support copied to clipboard

Improper (not ruby 3 compatible) args forwarding to the method signature verifier

Open malcolmohare opened this issue 1 year ago • 3 comments

Subject of the issue

Cross posting issue: https://github.com/rspec/rspec-expectations/issues/1451

The tldr of that issue is for a given function def foo(a=1, b:2) we get ambiguous args in the validator because the code is forwarding args in the ruby 2.x way. The following invocations appear identical to the verifier, but will cause different function parameter assignments.

foo(:b => 2)
foo({:b => 2})

The change I added to allow non-symbolic keys into the kwargs splat uncovered this bug in a very particular regression, see linked issue at the top for details.

I attempted to fix the issue, but as stated above, ran into the problem of unsolvable ambiguity.

The following is a snippet from the ruby3 docs describing the imcompatibility

https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/

Ruby 3 You need to explicitly delegate keyword arguments.

def foo(*args, **kwargs, &block)
  target(*args, **kwargs, &block)
end

Alternatively, if you do not need compatibility with Ruby 2.6 or prior and you don’t alter any arguments, you can use the new delegation syntax (...) that is introduced in Ruby 2.7.

def foo(...)
  target(...)
end

The fix is that the method signature verifier would need to change to accept the args in one of the two ways described in the snippet I linked in ruby 3 environments.
I am not familiar enough with the rspec code base to understand exactly how large a task that is, but I imagine its not small.

I'm open to having my previous contribution reverted until the fix is ready, since its caused at least one regression.

malcolmohare avatar Feb 25 '24 05:02 malcolmohare