diff options
| author | Jeremy Evans <code@jeremyevans.net> | 2025-05-29 22:32:09 -0700 |
|---|---|---|
| committer | Jeremy Evans <code@jeremyevans.net> | 2025-08-22 00:46:57 +0900 |
| commit | acb29f7fa1497463ed3bdd65549ef20b61beda64 (patch) | |
| tree | dfca2cfa76083f4d9f10892d966a3962e8724178 /vm_method.c | |
| parent | b0c80c2be8377ff02811b508ae79f18ec4a31f0e (diff) | |
Do not respect ruby2_keywords on method/proc with post arguments
Previously, ruby2_keywords could be used on a method or proc with
post arguments, but I don't think the behavior is desired:
```ruby
def a(*c, **kw) [c, kw] end
def b(*a, b) a(*a, b) end
ruby2_keywords(:b)
b({foo: 1}, bar: 1)
```
This changes ruby2_keywords to emit a warning and not set the
flag on a method/proc with post arguments.
While here, fix the ruby2_keywords specs for warnings, since they
weren't testing what they should be testing. They all warned
because the method didn't accept a rest argument, not because it
accepted a keyword or keyword rest argument.
Diffstat (limited to 'vm_method.c')
| -rw-r--r-- | vm_method.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/vm_method.c b/vm_method.c index 241e4cacef..03fb79cddd 100644 --- a/vm_method.c +++ b/vm_method.c @@ -2959,13 +2959,14 @@ rb_mod_ruby2_keywords(int argc, VALUE *argv, VALUE module) switch (me->def->type) { case VM_METHOD_TYPE_ISEQ: if (ISEQ_BODY(me->def->body.iseq.iseqptr)->param.flags.has_rest && + !ISEQ_BODY(me->def->body.iseq.iseqptr)->param.flags.has_post && !ISEQ_BODY(me->def->body.iseq.iseqptr)->param.flags.has_kw && !ISEQ_BODY(me->def->body.iseq.iseqptr)->param.flags.has_kwrest) { ISEQ_BODY(me->def->body.iseq.iseqptr)->param.flags.ruby2_keywords = 1; rb_clear_method_cache(module, name); } else { - rb_warn("Skipping set of ruby2_keywords flag for %"PRIsVALUE" (method accepts keywords or method does not accept argument splat)", QUOTE_ID(name)); + rb_warn("Skipping set of ruby2_keywords flag for %"PRIsVALUE" (method accepts keywords or post arguments or method does not accept argument splat)", QUOTE_ID(name)); } break; case VM_METHOD_TYPE_BMETHOD: { @@ -2978,13 +2979,14 @@ rb_mod_ruby2_keywords(int argc, VALUE *argv, VALUE module) const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(procval); const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq); if (ISEQ_BODY(iseq)->param.flags.has_rest && + !ISEQ_BODY(iseq)->param.flags.has_post && !ISEQ_BODY(iseq)->param.flags.has_kw && !ISEQ_BODY(iseq)->param.flags.has_kwrest) { ISEQ_BODY(iseq)->param.flags.ruby2_keywords = 1; rb_clear_method_cache(module, name); } else { - rb_warn("Skipping set of ruby2_keywords flag for %"PRIsVALUE" (method accepts keywords or method does not accept argument splat)", QUOTE_ID(name)); + rb_warn("Skipping set of ruby2_keywords flag for %"PRIsVALUE" (method accepts keywords or post arguments or method does not accept argument splat)", QUOTE_ID(name)); } break; } |
