diff options
author | Yuta Saito <[email protected]> | 2022-02-25 02:08:45 +0000 |
---|---|---|
committer | Yuta Saito <[email protected]> | 2022-03-02 17:13:40 +0900 |
commit | 2b5097b890161ddcb1ae9619699126f95a783bbd (patch) | |
tree | 8d220b387efeca82435323e18d2b737104930022 /vm_method.c | |
parent | fd2e1d3c4a0e248f710bc8f3abe94f343552026d (diff) |
vm_method.c: avoid signature mismatch in rb_f_notimplement call
`rb_f_notimplement` has a similar signature with arity=-1, but it has an
extra marker argument to distinguish it from other methods in
compile-time type check in rb_define_method.
This trick is introduced to override a given arity to be -1 since
https://github.com/ruby/ruby/commit/9ef51b0b89a10c8c401cb9f2337e47a25be72cbe
However, the trailing extra argument introduces a signature mismatch
between caller and callee expectation.
This patch adds rb_f_notimplement_internal, which has canonical arity=-1
signature, and makes rb_define_method family to inserts a method entry
with rb_f_notimplement_internal instead of rb_f_notimplement.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/5612
Diffstat (limited to 'vm_method.c')
-rw-r--r-- | vm_method.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/vm_method.c b/vm_method.c index b926654bdc..edbaad2396 100644 --- a/vm_method.c +++ b/vm_method.c @@ -323,14 +323,27 @@ rb_method_table_insert(VALUE klass, struct rb_id_table *table, ID method_id, con RB_OBJ_WRITTEN(table_owner, Qundef, (VALUE)me); } -VALUE -rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker) +// rb_f_notimplement has an extra trailing argument to distinguish it from other methods +// at compile-time to override arity to be -1. But the trailing argument introduces a +// signature mismatch between caller and callee, so rb_define_method family inserts a +// method entry with rb_f_notimplement_internal, which has canonical arity=-1 signature, +// instead of rb_f_notimplement. +NORETURN(static VALUE rb_f_notimplement_internal(int argc, const VALUE *argv, VALUE obj)); + +static VALUE +rb_f_notimplement_internal(int argc, const VALUE *argv, VALUE obj) { rb_notimplement(); UNREACHABLE_RETURN(Qnil); } +VALUE +rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker) +{ + rb_f_notimplement_internal(argc, argv, obj); +} + static void rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_visibility_t visi) { @@ -528,7 +541,7 @@ rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *de RB_OBJ_WRITE(me, &def->body.bmethod.defined_ractor, rb_ractor_self(GET_RACTOR())); return; case VM_METHOD_TYPE_NOTIMPLEMENTED: - setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), rb_f_notimplement, -1); + setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), rb_f_notimplement_internal, -1); return; case VM_METHOD_TYPE_OPTIMIZED: def->body.optimized = *(rb_method_optimized_t *)opts; |