From b460554d33e893cf4726c20946459a2f75792443 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 20 Feb 2026 14:25:48 +0900 Subject: [PATCH] vm.c: generalize pre-dispatch argument count check for C methods Replace check_method_noarg() with check_argument_count() that validates min <= argc <= max using the full aspec stored in mrb_method_t.flags. This catches ArgumentError earlier at dispatch time, before entering the C function. The old check only handled the special case of aspec==0 (NOARG). The new check extracts REQ, OPT, REST, POST, KEY, and KDICT from the aspec and validates accordingly. Keyword hash is counted as a positional arg only when the method doesn't accept keywords. Remove MRB_METHOD_NOARG_P macro from proc.h (subsumed by aspec check). Fix 15 incorrect aspec declarations across the codebase that were exposed by the stricter enforcement. Co-authored-by: Claude --- include/mruby/proc.h | 1 - mrbgems/mruby-array-ext/src/array.c | 2 +- mrbgems/mruby-errno/src/errno.c | 2 +- mrbgems/mruby-io/src/file.c | 2 +- mrbgems/mruby-method/src/method.c | 2 +- mrbgems/mruby-socket/src/socket.c | 4 +-- mrbgems/mruby-string-ext/src/string.c | 4 +-- mrbgems/mruby-task/src/task.c | 2 +- mrbgems/mruby-time/src/time.c | 2 +- src/array.c | 4 +-- src/class.c | 4 +-- src/hash.c | 2 +- src/string.c | 2 +- src/vm.c | 48 +++++++++++++++------------ 14 files changed, 42 insertions(+), 39 deletions(-) diff --git a/include/mruby/proc.h b/include/mruby/proc.h index 53cc9a4de..3a8a4054d 100644 --- a/include/mruby/proc.h +++ b/include/mruby/proc.h @@ -122,7 +122,6 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx); #define MRB_METHOD_VISIBILITY_MASK ((1 << 25) | (1 << 26)) #define MRB_METHOD_FUNC_P(m) ((m).flags&MRB_METHOD_FUNC_FL) -#define MRB_METHOD_NOARG_P(m) (((m).flags&0xffffff)==0) #define MRB_METHOD_FUNC(m) ((m).as.func) #define MRB_METHOD_FROM_FUNC(m,fn) do{(m).flags=MRB_METHOD_FUNC_FL;(m).as.func=(fn);}while(0) #define MRB_METHOD_FROM_PROC(m,pr) do{(m).flags=0;(m).as.proc=(pr);}while(0) diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c index d50b5b48d..c39e3f9ae 100644 --- a/mrbgems/mruby-array-ext/src/array.c +++ b/mrbgems/mruby-array-ext/src/array.c @@ -1564,7 +1564,7 @@ static const mrb_mt_entry array_ext_rom_entries[] = { MRB_MT_ENTRY(ary_fetch, MRB_SYM(__fetch), MRB_ARGS_REQ(3)), MRB_MT_ENTRY(ary_insert, MRB_SYM(insert), MRB_ARGS_ARG(1,-1)), MRB_MT_ENTRY(ary_deconstruct, MRB_SYM(deconstruct), MRB_ARGS_NONE()), - MRB_MT_ENTRY(ary_product_group, MRB_SYM(__product_group), MRB_ARGS_REQ(4)), + MRB_MT_ENTRY(ary_product_group, MRB_SYM(__product_group), MRB_ARGS_REQ(3)), MRB_MT_ENTRY(ary_combination_init, MRB_SYM(__combination_init), MRB_ARGS_REQ(2)), MRB_MT_ENTRY(ary_combination_next, MRB_SYM(__combination_next), MRB_ARGS_REQ(1)), }; diff --git a/mrbgems/mruby-errno/src/errno.c b/mrbgems/mruby-errno/src/errno.c index ea0a17893..37d82b954 100644 --- a/mrbgems/mruby-errno/src/errno.c +++ b/mrbgems/mruby-errno/src/errno.c @@ -314,7 +314,7 @@ mrb_mruby_errno_gem_init(mrb_state *mrb) struct RClass *sce = mrb_define_class_id(mrb, MRB_SYM(SystemCallError), E_STANDARD_ERROR); mrb_define_class_method_id(mrb, sce, MRB_SYM(_sys_fail), mrb_sce_sys_fail, MRB_ARGS_REQ(1)); mrb_define_method_id(mrb, sce, MRB_SYM(errno), mrb_sce_errno, MRB_ARGS_NONE()); - mrb_define_method_id(mrb, sce, MRB_SYM(initialize), mrb_sce_init_m, MRB_ARGS_ARG(1, 1)); + mrb_define_method_id(mrb, sce, MRB_SYM(initialize), mrb_sce_init_m, MRB_ARGS_OPT(2)); struct RClass *eno = mrb_define_module_id(mrb, MRB_SYM(Errno)); mrb_define_class_method_id(mrb, eno, MRB_SYM_Q(__errno_defined), mrb_errno_defined_p, MRB_ARGS_REQ(1)); diff --git a/mrbgems/mruby-io/src/file.c b/mrbgems/mruby-io/src/file.c index 3bdbc9ffd..52cf359f5 100644 --- a/mrbgems/mruby-io/src/file.c +++ b/mrbgems/mruby-io/src/file.c @@ -1146,7 +1146,7 @@ mrb_init_file(mrb_state *mrb) mrb_define_class_method_id(mrb, file, MRB_SYM(chmod), mrb_file_s_chmod, MRB_ARGS_REQ(1) | MRB_ARGS_REST()); mrb_define_class_method_id(mrb, file, MRB_SYM(readlink), mrb_file_s_readlink, MRB_ARGS_REQ(1)); - mrb_define_class_method_id(mrb, file, MRB_SYM(dirname), mrb_file_dirname, MRB_ARGS_REQ(1)); + mrb_define_class_method_id(mrb, file, MRB_SYM(dirname), mrb_file_dirname, MRB_ARGS_ARG(1,1)); mrb_define_class_method_id(mrb, file, MRB_SYM(basename), mrb_file_basename, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); mrb_define_class_method_id(mrb, file, MRB_SYM(extname), mrb_file_extname, MRB_ARGS_REQ(1)); mrb_define_class_method_id(mrb, file, MRB_SYM(join), mrb_file_join, MRB_ARGS_ANY()); diff --git a/mrbgems/mruby-method/src/method.c b/mrbgems/mruby-method/src/method.c index 095feac35..692ccddb1 100644 --- a/mrbgems/mruby-method/src/method.c +++ b/mrbgems/mruby-method/src/method.c @@ -394,7 +394,7 @@ method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) return MRB_METHOD_PROC(m); struct RProc *proc = mrb_proc_new_cfunc(mrb, MRB_METHOD_FUNC(m)); - if (MRB_METHOD_NOARG_P(m)) { + if (MRB_MT_ASPEC(m.flags) == 0) { proc->flags |= MRB_PROC_NOARG; } return proc; diff --git a/mrbgems/mruby-socket/src/socket.c b/mrbgems/mruby-socket/src/socket.c index c745a8457..270a35ecf 100644 --- a/mrbgems/mruby-socket/src/socket.c +++ b/mrbgems/mruby-socket/src/socket.c @@ -1341,8 +1341,8 @@ mrb_mruby_socket_gem_init(mrb_state* mrb) struct RClass *sock = mrb_define_class_id(mrb, MRB_SYM(Socket), bsock); mrb_define_class_method_id(mrb, sock, MRB_SYM(_accept), mrb_socket_accept, MRB_ARGS_REQ(1)); mrb_define_class_method_id(mrb, sock, MRB_SYM(_accept2), mrb_socket_accept2, MRB_ARGS_REQ(1)); - mrb_define_class_method_id(mrb, sock, MRB_SYM(_bind), mrb_socket_bind, MRB_ARGS_REQ(3)); - mrb_define_class_method_id(mrb, sock, MRB_SYM(_connect), mrb_socket_connect, MRB_ARGS_REQ(3)); + mrb_define_class_method_id(mrb, sock, MRB_SYM(_bind), mrb_socket_bind, MRB_ARGS_REQ(2)); + mrb_define_class_method_id(mrb, sock, MRB_SYM(_connect), mrb_socket_connect, MRB_ARGS_REQ(2)); mrb_define_class_method_id(mrb, sock, MRB_SYM(_listen), mrb_socket_listen, MRB_ARGS_REQ(2)); mrb_define_class_method_id(mrb, sock, MRB_SYM(_sockaddr_family), mrb_socket_sockaddr_family, MRB_ARGS_REQ(1)); mrb_define_class_method_id(mrb, sock, MRB_SYM(_socket), mrb_socket_socket, MRB_ARGS_REQ(3)); diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index bbdb922a8..d516d1da9 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -2257,8 +2257,8 @@ static const mrb_mt_entry string_ext_rom_entries[] = { MRB_MT_ENTRY(str_del_suffix, MRB_SYM(delete_suffix), MRB_ARGS_REQ(1)), MRB_MT_ENTRY(str_casecmp, MRB_SYM(casecmp), MRB_ARGS_REQ(1)), MRB_MT_ENTRY(str_casecmp_p, MRB_SYM_Q(casecmp), MRB_ARGS_REQ(1)), - MRB_MT_ENTRY(str_uplus, MRB_OPSYM(plus), MRB_ARGS_REQ(1)), - MRB_MT_ENTRY(str_uminus, MRB_OPSYM(minus), MRB_ARGS_REQ(1)), + MRB_MT_ENTRY(str_uplus, MRB_OPSYM(plus), MRB_ARGS_NONE()), + MRB_MT_ENTRY(str_uminus, MRB_OPSYM(minus), MRB_ARGS_NONE()), MRB_MT_ENTRY(str_ascii_only_p, MRB_SYM_Q(ascii_only), MRB_ARGS_NONE()), MRB_MT_ENTRY(str_b, MRB_SYM(b), MRB_ARGS_NONE()), MRB_MT_ENTRY(str_lines, MRB_SYM(__lines), MRB_ARGS_NONE()), diff --git a/mrbgems/mruby-task/src/task.c b/mrbgems/mruby-task/src/task.c index afefe957c..964969ab6 100644 --- a/mrbgems/mruby-task/src/task.c +++ b/mrbgems/mruby-task/src/task.c @@ -1530,7 +1530,7 @@ mrb_mruby_task_gem_init(mrb_state *mrb) MRB_SET_INSTANCE_TT(task_class, MRB_TT_DATA); /* Class methods */ - mrb_define_class_method_id(mrb, task_class, MRB_SYM(new), mrb_task_s_new, MRB_ARGS_BLOCK()); + mrb_define_class_method_id(mrb, task_class, MRB_SYM(new), mrb_task_s_new, MRB_ARGS_KEY(2,0)|MRB_ARGS_BLOCK()); mrb_define_class_method_id(mrb, task_class, MRB_SYM(current), mrb_task_s_current, MRB_ARGS_NONE()); mrb_define_class_method_id(mrb, task_class, MRB_SYM(list), mrb_task_s_list, MRB_ARGS_NONE()); mrb_define_class_method_id(mrb, task_class, MRB_SYM(pass), mrb_task_s_pass, MRB_ARGS_NONE()); diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 98809be1a..30fa80fc2 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -1699,7 +1699,7 @@ static const mrb_mt_entry time_rom_entries[] = { MRB_MT_ENTRY(time_yday, MRB_SYM(yday), MRB_ARGS_NONE()), /* 15.2.19.7.31 */ MRB_MT_ENTRY(time_year, MRB_SYM(year), MRB_ARGS_NONE()), /* 15.2.19.7.32 */ MRB_MT_ENTRY(time_zone, MRB_SYM(zone), MRB_ARGS_NONE()), /* 15.2.19.7.33 */ - MRB_MT_ENTRY(time_init, MRB_SYM(initialize), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.19.7.16 */ + MRB_MT_ENTRY(time_init, MRB_SYM(initialize), MRB_ARGS_OPT(7) | MRB_MT_PRIVATE), /* 15.2.19.7.16 */ MRB_MT_ENTRY(time_init_copy, MRB_SYM(initialize_copy), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.19.7.17 */ MRB_MT_ENTRY(time_sunday, MRB_SYM_Q(sunday), MRB_ARGS_NONE()), MRB_MT_ENTRY(time_monday, MRB_SYM_Q(monday), MRB_ARGS_NONE()), diff --git a/src/array.c b/src/array.c index 048f5c375..235580afb 100644 --- a/src/array.c +++ b/src/array.c @@ -2264,7 +2264,7 @@ static const mrb_mt_entry array_rom_entries[] = { MRB_MT_ENTRY(mrb_ary_eq, MRB_OPSYM(eq), MRB_ARGS_REQ(1)), MRB_MT_ENTRY(mrb_ary_eql, MRB_SYM_Q(eql), MRB_ARGS_REQ(1)), MRB_MT_ENTRY(mrb_ary_first, MRB_SYM(first), MRB_ARGS_OPT(1)), /* 15.2.12.5.13 */ - MRB_MT_ENTRY(mrb_ary_index_m, MRB_SYM(index), MRB_ARGS_REQ(1)), /* 15.2.12.5.14 */ + MRB_MT_ENTRY(mrb_ary_index_m, MRB_SYM(index), MRB_ARGS_OPT(1)), /* 15.2.12.5.14 */ MRB_MT_ENTRY(mrb_ary_init, MRB_SYM(initialize), MRB_ARGS_OPT(2) | MRB_MT_PRIVATE), /* 15.2.12.5.15 */ MRB_MT_ENTRY(mrb_ary_replace_m, MRB_SYM(initialize_copy), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.12.5.16 */ MRB_MT_ENTRY(mrb_ary_join_m, MRB_SYM(join), MRB_ARGS_OPT(1)), /* 15.2.12.5.17 */ @@ -2275,7 +2275,7 @@ static const mrb_mt_entry array_rom_entries[] = { MRB_MT_ENTRY(mrb_ary_replace_m, MRB_SYM(replace), MRB_ARGS_REQ(1)), /* 15.2.12.5.23 */ MRB_MT_ENTRY(mrb_ary_reverse, MRB_SYM(reverse), MRB_ARGS_NONE()), /* 15.2.12.5.24 */ MRB_MT_ENTRY(mrb_ary_reverse_bang, MRB_SYM_B(reverse), MRB_ARGS_NONE()), /* 15.2.12.5.25 */ - MRB_MT_ENTRY(mrb_ary_rindex_m, MRB_SYM(rindex), MRB_ARGS_REQ(1)), /* 15.2.12.5.26 */ + MRB_MT_ENTRY(mrb_ary_rindex_m, MRB_SYM(rindex), MRB_ARGS_OPT(1)), /* 15.2.12.5.26 */ MRB_MT_ENTRY(mrb_ary_shift_m, MRB_SYM(shift), MRB_ARGS_OPT(1)), /* 15.2.12.5.27 */ MRB_MT_ENTRY(mrb_ary_size, MRB_SYM(size), MRB_ARGS_NONE()), /* 15.2.12.5.28 */ MRB_MT_ENTRY(mrb_ary_aget, MRB_SYM(slice), MRB_ARGS_ARG(1,1)), /* 15.2.12.5.29 */ diff --git a/src/class.c b/src/class.c index 7a626abe3..0ca296db2 100644 --- a/src/class.c +++ b/src/class.c @@ -4296,7 +4296,7 @@ static const mrb_mt_entry mod_rom_entries[] = { MRB_MT_ENTRY(mod_define_method, MRB_SYM(define_method), MRB_ARGS_ARG(1,1)), MRB_MT_ENTRY(mrb_mod_dup, MRB_SYM(dup), MRB_ARGS_NONE()), MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(extended), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.2.4.26 */ - MRB_MT_ENTRY(mrb_mod_include, MRB_SYM(include), MRB_ARGS_REQ(1)), /* 15.2.2.4.27 */ + MRB_MT_ENTRY(mrb_mod_include, MRB_SYM(include), MRB_ARGS_ANY()), /* 15.2.2.4.27 */ MRB_MT_ENTRY(mrb_mod_include_p, MRB_SYM_Q(include), MRB_ARGS_REQ(1)), /* 15.2.2.4.28 */ MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(included), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.2.4.29 */ MRB_MT_ENTRY(mrb_mod_initialize, MRB_SYM(initialize), MRB_ARGS_NONE() | MRB_MT_PRIVATE), /* 15.2.2.4.31 */ @@ -4307,7 +4307,7 @@ static const mrb_mt_entry mod_rom_entries[] = { MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(method_undefined), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), MRB_MT_ENTRY(mrb_mod_module_eval, MRB_SYM(module_eval), MRB_ARGS_ANY()), /* 15.2.2.4.35 */ MRB_MT_ENTRY(mrb_mod_module_function, MRB_SYM(module_function), MRB_ARGS_ANY() | MRB_MT_PRIVATE), - MRB_MT_ENTRY(mrb_mod_prepend, MRB_SYM(prepend), MRB_ARGS_REQ(1)), + MRB_MT_ENTRY(mrb_mod_prepend, MRB_SYM(prepend), MRB_ARGS_ANY()), MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(prepended), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), MRB_MT_ENTRY(mrb_mod_private, MRB_SYM(private), MRB_ARGS_ANY() | MRB_MT_PRIVATE), /* 15.2.2.4.36 */ MRB_MT_ENTRY(mrb_mod_protected, MRB_SYM(protected), MRB_ARGS_ANY() | MRB_MT_PRIVATE), /* 15.2.2.4.37 */ diff --git a/src/hash.c b/src/hash.c index 597059540..20e1f8426 100644 --- a/src/hash.c +++ b/src/hash.c @@ -2336,7 +2336,7 @@ static const mrb_mt_entry hash_rom_entries[] = { MRB_MT_ENTRY(mrb_hash_to_hash, MRB_SYM(to_hash), MRB_ARGS_NONE()), MRB_MT_ENTRY(mrb_hash_assoc, MRB_SYM(assoc), MRB_ARGS_REQ(1)), MRB_MT_ENTRY(mrb_hash_rassoc, MRB_SYM(rassoc), MRB_ARGS_REQ(1)), - MRB_MT_ENTRY(mrb_hash_merge_m, MRB_SYM(__merge), MRB_ARGS_REQ(1)), + MRB_MT_ENTRY(mrb_hash_merge_m, MRB_SYM(__merge), MRB_ARGS_ANY()), MRB_MT_ENTRY(mrb_hash_compact, MRB_SYM(__compact), MRB_ARGS_NONE()), /* implementation of Hash#compact! */ MRB_MT_ENTRY(mrb_hash_pat_values, MRB_SYM(__pat_values), MRB_ARGS_REQ(1)), /* for pattern matching keys */ MRB_MT_ENTRY(mrb_hash_except_keys, MRB_SYM(__except), MRB_ARGS_REQ(1)), /* for pattern matching **rest */ diff --git a/src/string.c b/src/string.c index 1262b9819..15fcf9123 100644 --- a/src/string.c +++ b/src/string.c @@ -3529,7 +3529,7 @@ static const mrb_mt_entry string_rom_entries[] = { MRB_MT_ENTRY(mrb_str_hash_m, MRB_SYM(hash), MRB_ARGS_NONE()), /* 15.2.10.5.20 */ MRB_MT_ENTRY(mrb_str_include, MRB_SYM_Q(include), MRB_ARGS_REQ(1)), /* 15.2.10.5.21 */ MRB_MT_ENTRY(mrb_str_index_m, MRB_SYM(index), MRB_ARGS_ARG(1,1)), /* 15.2.10.5.22 */ - MRB_MT_ENTRY(mrb_str_init, MRB_SYM(initialize), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.10.5.23 */ + MRB_MT_ENTRY(mrb_str_init, MRB_SYM(initialize), MRB_ARGS_OPT(1) | MRB_MT_PRIVATE), /* 15.2.10.5.23 */ MRB_MT_ENTRY(mrb_str_replace, MRB_SYM(initialize_copy), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.10.5.24 */ MRB_MT_ENTRY(mrb_str_intern, MRB_SYM(intern), MRB_ARGS_NONE()), /* 15.2.10.5.25 */ MRB_MT_ENTRY(mrb_str_size, MRB_SYM(length), MRB_ARGS_NONE()), /* 15.2.10.5.26 */ diff --git a/src/vm.c b/src/vm.c index 63b5f8401..fad48c61f 100644 --- a/src/vm.c +++ b/src/vm.c @@ -870,17 +870,23 @@ mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, cons } static void -check_method_noarg(mrb_state *mrb, const mrb_callinfo *ci) +check_argument_count(mrb_state *mrb, const mrb_callinfo *ci, mrb_aspec aspec) { - mrb_int argc = ci->n == CALL_MAXARGS ? RARRAY_LEN(ci->stack[1]) : ci->n; - if (ci->nk > 0) { + mrb_int argc = ci->n; + if (mrb_unlikely(argc == CALL_MAXARGS)) { + argc = RARRAY_LEN(ci->stack[1]); + } + /* keyword hash counts as positional if method doesn't accept keywords */ + if (ci->nk > 0 && MRB_ASPEC_KEY(aspec) == 0 && !MRB_ASPEC_KDICT(aspec)) { mrb_value kdict = ci->stack[mrb_ci_kidx(ci)]; - if (!(mrb_hash_p(kdict) && mrb_hash_empty_p(mrb, kdict))) { + if (mrb_hash_p(kdict) && !mrb_hash_empty_p(mrb, kdict)) { argc++; } } - if (argc > 0) { - mrb_argnum_error(mrb, argc, 0, 0); + int min = MRB_ASPEC_REQ(aspec) + MRB_ASPEC_POST(aspec); + int max = MRB_ASPEC_REST(aspec) ? -1 : min + MRB_ASPEC_OPT(aspec); + if (mrb_unlikely(argc < min || (max >= 0 && argc > max))) { + mrb_argnum_error(mrb, argc, min, max); } } @@ -895,7 +901,7 @@ exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p) CI_PROC_SET(ci, p); if (MRB_PROC_CFUNC_P(p)) { if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) { - check_method_noarg(mrb, ci); + check_argument_count(mrb, ci, 0); } return MRB_PROC_CFUNC(p)(mrb, self); } @@ -925,7 +931,7 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p) mrb_value ret; if (MRB_PROC_CFUNC_P(p)) { if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) { - check_method_noarg(mrb, ci); + check_argument_count(mrb, ci, 0); } ci = cipush(mrb, 0, CINFO_DIRECT, CI_TARGET_CLASS(ci), p, NULL, ci->mid, ci->n|(ci->nk<<4)); mrb->exc = NULL; @@ -1037,18 +1043,18 @@ send_method(mrb_state *mrb, mrb_value self, mrb_bool pub) ci->n--; } - const struct RProc *p; - if (MRB_METHOD_PROC_P(m)) { - p = MRB_METHOD_PROC(m); - /* handle alias */ - MRB_PROC_RESOLVE_ALIAS(ci, p); - CI_PROC_SET(ci, p); + if (MRB_METHOD_FUNC_P(m)) { + check_argument_count(mrb, ci, MRB_MT_ASPEC(m.flags)); + return MRB_METHOD_FUNC(m)(mrb, self); } - if (MRB_METHOD_CFUNC_P(m)) { - if (MRB_METHOD_NOARG_P(m) && (ci->n > 0 || ci->nk > 0)) { - check_method_noarg(mrb, ci); + const struct RProc *p = MRB_METHOD_PROC(m); + MRB_PROC_RESOLVE_ALIAS(ci, p); + CI_PROC_SET(ci, p); + if (MRB_PROC_CFUNC_P(p)) { + if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) { + check_argument_count(mrb, ci, 0); } - return MRB_METHOD_CFUNC(m)(mrb, self); + return MRB_PROC_CFUNC(p)(mrb, self); } return exec_irep(mrb, self, p); } @@ -2319,15 +2325,13 @@ RETRY_TRY_BLOCK: } else { if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) { - check_method_noarg(mrb, ci); + check_argument_count(mrb, ci, 0); } recv = MRB_PROC_CFUNC(p)(mrb, recv); } } else { - if (MRB_METHOD_NOARG_P(m) && (ci->n > 0 || ci->nk > 0)) { - check_method_noarg(mrb, ci); - } + check_argument_count(mrb, ci, MRB_MT_ASPEC(m.flags)); recv = MRB_METHOD_FUNC(m)(mrb, recv); }