Skip to content

Commit 1f6d845

Browse files
nicholasdowerk0kubun
authored andcommitted
[Bug #21313] Handle it in rescue and ensure blocks.
The following is crashing for me: ```shell ruby --yjit --yjit-call-threshold=1 -e '1.tap { raise rescue p it }' ruby: YJIT has panicked. More info to follow... thread '<unnamed>' panicked at ./yjit/src/codegen.rs:2402:14: ... ``` It seems `it` sometimes points to the wrong value: ```shell ruby -e '1.tap { raise rescue p it }' false ruby -e '1.tap { begin; raise; ensure; p it; end } rescue nil' false ``` But only when `$!` is set: ```shell ruby -e '1.tap { begin; nil; ensure; p it; end }' 1 ruby -e '1.tap { begin; nil; rescue; ensure; p it; end }' 1 ruby -e '1.tap { begin; raise; rescue; ensure; p it; end }' 1 ```
1 parent dbd8325 commit 1f6d845

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

prism_compile.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9620,7 +9620,19 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
96209620
// -> { it }
96219621
// ^^
96229622
if (!popped) {
9623-
PUSH_GETLOCAL(ret, location, scope_node->local_table_for_iseq_size, 0);
9623+
pm_scope_node_t *current_scope_node = scope_node;
9624+
int level = 0;
9625+
9626+
while (current_scope_node) {
9627+
if (current_scope_node->parameters && PM_NODE_TYPE_P(current_scope_node->parameters, PM_IT_PARAMETERS_NODE)) {
9628+
PUSH_GETLOCAL(ret, location, current_scope_node->local_table_for_iseq_size, level);
9629+
return;
9630+
}
9631+
9632+
current_scope_node = current_scope_node->previous;
9633+
level++;
9634+
}
9635+
rb_bug("Local `it` does not exist");
96249636
}
96259637

96269638
return;

test/ruby/test_syntax.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,6 +1946,14 @@ def test_it
19461946
end
19471947
assert_valid_syntax('proc {def foo(_);end;it}')
19481948
assert_syntax_error('p { [it **2] }', /unexpected \*\*/)
1949+
assert_equal(1, eval('1.then { raise rescue it }'))
1950+
assert_equal(2, eval('1.then { 2.then { raise rescue it } }'))
1951+
assert_equal(3, eval('3.then { begin; raise; rescue; it; end }'))
1952+
assert_equal(4, eval('4.tap { begin; raise ; rescue; raise rescue it; end; }'))
1953+
assert_equal(5, eval('a = 0; 5.then { begin; nil; ensure; a = it; end }; a'))
1954+
assert_equal(6, eval('a = 0; 6.then { begin; nil; rescue; ensure; a = it; end }; a'))
1955+
assert_equal(7, eval('a = 0; 7.then { begin; raise; ensure; a = it; end } rescue a'))
1956+
assert_equal(8, eval('a = 0; 8.then { begin; raise; rescue; ensure; a = it; end }; a'))
19491957
end
19501958

19511959
def test_value_expr_in_condition

0 commit comments

Comments
 (0)