diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c index 7e21a21f7eb2d8..936fb0f81baad7 100644 --- a/ext/strscan/strscan.c +++ b/ext/strscan/strscan.c @@ -822,7 +822,7 @@ strscan_scan(VALUE self, VALUE re) * :include: strscan/link_refs.txt * * call-seq: - * match?(pattern) -> updated_position or nil + * match?(pattern) -> match_size or nil * * Attempts to [match][17] the given `pattern` * at the beginning of the [target substring][3]; @@ -882,7 +882,7 @@ strscan_match_p(VALUE self, VALUE re) /* * :markup: markdown * call-seq: - * skip(pattern) match_size or nil + * skip(pattern) -> match_size or nil * * :include: strscan/link_refs.txt * :include: strscan/methods/skip.md @@ -956,7 +956,7 @@ strscan_check(VALUE self, VALUE re) /* * call-seq: - * scan_full(pattern, advance_pointer_p, return_string_p) -> matched_substring or nil + * scan_full(pattern, advance_pointer_p, return_string_p) -> matched_substring or length or nil * * Equivalent to one of the following: * @@ -1202,7 +1202,7 @@ strscan_getch(VALUE self) /* * call-seq: - * scan_byte -> integer_byte + * scan_byte -> integer_byte or nil * * Scans one byte and returns it as an integer. * This method is not multibyte character sensitive. diff --git a/test/fiber/test_thread.rb b/test/fiber/test_thread.rb index 0247f330d94403..4d2fbde9ed20a8 100644 --- a/test/fiber/test_thread.rb +++ b/test/fiber/test_thread.rb @@ -156,16 +156,20 @@ def test_broken_unblock end def test_thread_join_hang + inner = nil thread = Thread.new do scheduler = SleepingUnblockScheduler.new Fiber.set_scheduler scheduler Fiber.schedule do - Thread.new{sleep(0.01)}.value + inner = Thread.new{sleep(0.01)} + inner.value end end thread.join + ensure + inner&.join end end diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb index db1fdc8e25a3c5..75ed1a7534dc42 100644 --- a/test/ruby/test_defined.rb +++ b/test/ruby/test_defined.rb @@ -62,6 +62,34 @@ def test_defined_protected_method f.bar(Class.new(Foo).new) { |v| assert(v, "inherited protected method") } end + module ProtectedInModule + def m + :m + end + protected :m + def call_m(o) + o.m + end + def defined_m(o) + defined?(o.m) + end + end + class ProtectedIncluderA + include ProtectedInModule + end + class ProtectedIncluderB + include ProtectedInModule + end + + def test_defined_protected_method_in_included_module + a = ProtectedIncluderA.new + b = ProtectedIncluderB.new + assert_equal(:m, a.call_m(a)) + assert_equal(:m, a.call_m(b)) + assert_equal("method", a.defined_m(a)) + assert_equal("method", a.defined_m(b)) + end + def test_defined_undefined_method f = Foo.new assert_nil(defined?(f.quux)) # undefined method diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 783246a7efc513..75d5023566e7c6 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -5485,21 +5485,21 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_ break; case DEFINED_METHOD:{ VALUE klass = CLASS_OF(v); - const rb_method_entry_t *me = rb_method_entry_with_refinements(klass, SYM2ID(obj), NULL); + const rb_callable_method_entry_t *cme = rb_callable_method_entry_with_refinements(klass, SYM2ID(obj), NULL); - if (me) { - switch (METHOD_ENTRY_VISI(me)) { + if (cme) { + switch (METHOD_ENTRY_VISI(cme)) { case METHOD_VISI_PRIVATE: break; case METHOD_VISI_PROTECTED: - if (!rb_obj_is_kind_of(GET_SELF(), rb_class_real(me->defined_class))) { + if (!rb_obj_is_kind_of(GET_SELF(), vm_defined_class_for_protected_call(cme))) { break; } case METHOD_VISI_PUBLIC: return true; break; default: - rb_bug("vm_defined: unreachable: %u", (unsigned int)METHOD_ENTRY_VISI(me)); + rb_bug("vm_defined: unreachable: %u", (unsigned int)METHOD_ENTRY_VISI(cme)); } } else {