mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Struct setter's parameters == [:req, :_]
fix [Bug #18405] Note that the parameter name `_` is not a spec, so we shouldn't rely on this behavior.
This commit is contained in:
parent
4d0cb1a54b
commit
6659253cc6
Notes:
git
2021-12-13 10:24:24 +09:00
2 changed files with 80 additions and 6 deletions
69
proc.c
69
proc.c
|
@ -2910,6 +2910,69 @@ rb_method_location(VALUE method)
|
|||
return method_def_location(rb_method_def(method));
|
||||
}
|
||||
|
||||
static const rb_method_definition_t *
|
||||
vm_proc_method_def(VALUE procval)
|
||||
{
|
||||
const rb_proc_t *proc;
|
||||
const struct rb_block *block;
|
||||
const struct vm_ifunc *ifunc;
|
||||
|
||||
GetProcPtr(procval, proc);
|
||||
block = &proc->block;
|
||||
|
||||
if (vm_block_type(block) == block_type_ifunc &&
|
||||
IS_METHOD_PROC_IFUNC(ifunc = block->as.captured.code.ifunc)) {
|
||||
return rb_method_def((VALUE)ifunc->data);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE
|
||||
method_def_parameters(const rb_method_definition_t *def)
|
||||
{
|
||||
const rb_iseq_t *iseq;
|
||||
const rb_method_definition_t *bmethod_def;
|
||||
|
||||
switch (def->type) {
|
||||
case VM_METHOD_TYPE_ISEQ:
|
||||
iseq = method_def_iseq(def);
|
||||
return rb_iseq_parameters(iseq, 0);
|
||||
case VM_METHOD_TYPE_BMETHOD:
|
||||
if ((iseq = method_def_iseq(def)) != NULL) {
|
||||
return rb_iseq_parameters(iseq, 0);
|
||||
}
|
||||
else if ((bmethod_def = vm_proc_method_def(def->body.bmethod.proc)) != NULL) {
|
||||
return method_def_parameters(bmethod_def);
|
||||
}
|
||||
break;
|
||||
|
||||
case VM_METHOD_TYPE_ALIAS:
|
||||
return method_def_parameters(def->body.alias.original_me->def);
|
||||
|
||||
case VM_METHOD_TYPE_OPTIMIZED:
|
||||
if (def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET) {
|
||||
VALUE param = rb_ary_new_from_args(2, ID2SYM(rb_intern("req")), ID2SYM(rb_intern("_")));
|
||||
return rb_ary_new_from_args(1, param);
|
||||
}
|
||||
break;
|
||||
|
||||
case VM_METHOD_TYPE_CFUNC:
|
||||
case VM_METHOD_TYPE_ATTRSET:
|
||||
case VM_METHOD_TYPE_IVAR:
|
||||
case VM_METHOD_TYPE_ZSUPER:
|
||||
case VM_METHOD_TYPE_UNDEF:
|
||||
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
||||
case VM_METHOD_TYPE_MISSING:
|
||||
case VM_METHOD_TYPE_REFINED:
|
||||
break;
|
||||
}
|
||||
|
||||
return rb_unnamed_parameters(method_def_aritry(def));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* meth.parameters -> array
|
||||
|
@ -2932,11 +2995,7 @@ rb_method_location(VALUE method)
|
|||
static VALUE
|
||||
rb_method_parameters(VALUE method)
|
||||
{
|
||||
const rb_iseq_t *iseq = rb_method_iseq(method);
|
||||
if (!iseq) {
|
||||
return rb_unnamed_parameters(method_arity(method));
|
||||
}
|
||||
return rb_iseq_parameters(iseq, 0);
|
||||
return method_def_parameters(rb_method_def(method));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -497,6 +497,21 @@ module TestStruct
|
|||
assert_equal(42, x.public_send("a"))
|
||||
end
|
||||
|
||||
def test_parameters
|
||||
klass = @Struct.new(:a)
|
||||
assert_equal [], klass.instance_method(:a).parameters
|
||||
# NOTE: :_ may not be a spec.
|
||||
assert_equal [[:req, :_]], klass.instance_method(:a=).parameters
|
||||
|
||||
klass.module_eval do
|
||||
define_method(:b=, &klass.new.method(:a=).to_proc)
|
||||
alias c= a=
|
||||
end
|
||||
|
||||
assert_equal [[:req, :_]], klass.instance_method(:b=).parameters
|
||||
assert_equal [[:req, :_]], klass.instance_method(:c=).parameters
|
||||
end
|
||||
|
||||
class TopStruct < Test::Unit::TestCase
|
||||
include TestStruct
|
||||
|
||||
|
|
Loading…
Reference in a new issue