Skip to content

Commit c859e15

Browse files
committed
Handle defined? with call chains with blocks
Ensures we can handle expressions like `defined?(a {}.b)`.
1 parent 11c9e4f commit c859e15

File tree

2 files changed

+9
-2
lines changed

2 files changed

+9
-2
lines changed

prism_compile.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3994,9 +3994,11 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_l
39943994
return;
39953995
}
39963996
case PM_CALL_NODE: {
3997+
#define BLOCK_P(cast) ((cast)->block != NULL && PM_NODE_TYPE_P((cast)->block, PM_BLOCK_NODE))
3998+
39973999
const pm_call_node_t *cast = ((const pm_call_node_t *) node);
39984000

3999-
if (cast->block != NULL && PM_NODE_TYPE_P(cast->block, PM_BLOCK_NODE)) {
4001+
if (BLOCK_P(cast)) {
40004002
dtype = DEFINED_EXPR;
40014003
break;
40024004
}
@@ -4016,7 +4018,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_l
40164018
if (cast->receiver) {
40174019
pm_compile_defined_expr0(iseq, cast->receiver, node_location, ret, popped, scope_node, true, lfinish, true);
40184020

4019-
if (PM_NODE_TYPE_P(cast->receiver, PM_CALL_NODE)) {
4021+
if (PM_NODE_TYPE_P(cast->receiver, PM_CALL_NODE) && !BLOCK_P((const pm_call_node_t *) cast->receiver)) {
40204022
PUSH_INSNL(ret, location, branchunless, lfinish[2]);
40214023

40224024
const pm_call_node_t *receiver = (const pm_call_node_t *) cast->receiver;
@@ -4038,6 +4040,8 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_l
40384040
}
40394041

40404042
return;
4043+
4044+
#undef BLOCK_P
40414045
}
40424046
case PM_YIELD_NODE:
40434047
PUSH_INSN(ret, location, putnil);

test/ruby/test_compile_prism.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ def test_DefinedNode
207207
assert_prism_eval("defined?(a(itself))")
208208
assert_prism_eval("defined?(itself(itself))")
209209

210+
# method chain with a block on the inside
211+
assert_prism_eval("defined?(itself { 1 }.itself)")
212+
210213
# Method chain on a constant
211214
assert_prism_eval(<<~RUBY)
212215
class PrismDefinedNode

0 commit comments

Comments
 (0)