Skip to content

Commit 7b5cb93

Browse files
committed
[GR-18163] Support refinements for Kernel#respond_to? (#2120)
PullRequest: truffleruby/2060
2 parents ff47099 + 7daf570 commit 7b5cb93

File tree

6 files changed

+19
-10
lines changed

6 files changed

+19
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Compatibility:
4848
* Avoid infinite recursion when redefining `Warning#warn` and calling `Kernel#warn` (#2109).
4949
* Convert objects with `#to_path` in `$LOAD_PATH` (#2119).
5050
* Handle the functions being native for `rb_thread_call_without_gvl()` (#2090).
51+
* Support refinements for Kernel#respond_to? (#2120, @ssnickolay)
5152

5253
Performance:
5354

lib/truffle/truffle/cext.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,12 @@ def rb_class_real(ruby_class)
412412
ruby_class
413413
end
414414

415-
def rb_obj_respond_to(object, id, priv)
416-
Primitive.object_respond_to?(object, id, priv != 0)
415+
def rb_obj_respond_to(object, name, priv)
416+
object.respond_to?(name, priv != 0)
417+
end
418+
419+
def rb_respond_to(object, name)
420+
object.respond_to?(name, false)
417421
end
418422

419423
def rb_check_convert_type(obj, type_name, method)
@@ -842,10 +846,6 @@ def rb_funcall_with_block(recv, meth, args, block)
842846
recv.public_send(meth, *args, &block)
843847
end
844848

845-
def rb_respond_to(object, name)
846-
object.respond_to?(name)
847-
end
848-
849849
def rb_funcallv_public(recv, meth, args)
850850
recv.public_send(meth, *args)
851851
end

spec/tags/core/module/refine_tags.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
fails:Module#refine for methods accessed indirectly is honored by Kernel#respond_to?
21
slow:Module#refine method lookup looks in the included modules for builtin methods

src/main/c/cext/range.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ VALUE rb_range_new(VALUE beg, VALUE end, int exclude_end) {
1515
*/
1616
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp) {
1717
if (!rb_obj_is_kind_of(range, rb_cRange)) {
18-
if (!RTEST(RUBY_INVOKE(range, "respond_to?", rb_intern("begin")))) return Qfalse;
19-
if (!RTEST(RUBY_INVOKE(range, "respond_to?", rb_intern("end")))) return Qfalse;
18+
if (!rb_respond_to(range, rb_intern("begin"))) return Qfalse;
19+
if (!rb_respond_to(range, rb_intern("end"))) return Qfalse;
2020
}
2121

2222
*begp = RUBY_INVOKE(range, "begin");

src/main/java/org/truffleruby/core/kernel/KernelNodes.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,7 @@ public abstract static class RespondToNode extends CoreMethodNode {
15591559
@Child private InternalRespondToNode dispatch;
15601560
@Child private InternalRespondToNode dispatchIgnoreVisibility;
15611561
@Child private InternalRespondToNode dispatchRespondToMissing;
1562+
@Child private ReadCallerFrameNode readCallerFrame = ReadCallerFrameNode.create();
15621563
@Child private DispatchNode respondToMissingNode;
15631564
@Child private BooleanCastNode booleanCastNode;
15641565
private final ConditionProfile ignoreVisibilityProfile = ConditionProfile.create();
@@ -1587,6 +1588,7 @@ protected boolean doesRespondToString(
15871588
boolean includeProtectedAndPrivate,
15881589
@Cached ToJavaStringNode toJavaString) {
15891590
final boolean ret;
1591+
useCallerRefinements(frame);
15901592

15911593
if (ignoreVisibilityProfile.profile(includeProtectedAndPrivate)) {
15921594
ret = dispatchIgnoreVisibility.execute(frame, object, toJavaString.executeToJavaString(name));
@@ -1616,6 +1618,7 @@ protected boolean doesRespondToSymbol(
16161618
boolean includeProtectedAndPrivate,
16171619
@Cached ToJavaStringNode toJavaString) {
16181620
final boolean ret;
1621+
useCallerRefinements(frame);
16191622

16201623
if (ignoreVisibilityProfile.profile(includeProtectedAndPrivate)) {
16211624
ret = dispatchIgnoreVisibility.execute(frame, object, toJavaString.executeToJavaString(name));
@@ -1648,6 +1651,13 @@ private boolean respondToMissing(VirtualFrame frame, Object object, RubySymbol n
16481651
return booleanCastNode.executeToBoolean(
16491652
respondToMissingNode.call(object, "respond_to_missing?", name, includeProtectedAndPrivate));
16501653
}
1654+
1655+
private void useCallerRefinements(VirtualFrame frame) {
1656+
if (frame != null) {
1657+
DeclarationContext context = RubyArguments.getDeclarationContext(readCallerFrame.execute(frame));
1658+
RubyArguments.setDeclarationContext(frame, context);
1659+
}
1660+
}
16511661
}
16521662

16531663
@CoreMethod(names = "respond_to_missing?", required = 2)

test/mri/excludes/TestRefinement.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
exclude :test_prepend_after_refine, "needs investigation"
44
exclude :test_refine_prepended_class, "needs investigation"
55
exclude :test_refine_with_proc, "needs investigation"
6-
exclude :test_respond_to_should_use_refinements, "needs investigation"
76
exclude :test_tostring, "needs investigation"
87
exclude :test_undef_original_method, "needs investigation"
98
exclude :test_used_modules, "needs investigation"

0 commit comments

Comments
 (0)