Skip to content

Commit 86b5389

Browse files
committed
Fix declaring a variable inside the case target expression
* Fixes #3377
1 parent 16e1906 commit 86b5389

File tree

4 files changed

+25
-3
lines changed

4 files changed

+25
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Bug fixes:
1313
* Fix some C API functions which were failing when called with Ruby values represented as Java primitives (#3352, @eregon).
1414
* Fix `IO.select([io], nil, [io])` on macOS, it was hanging due to a bug in macOS `poll(2)` (#3346, @eregon, @andrykonchin).
1515
* Run context cleanup such as showing the output of tools when `SignalException` and `Interrupt` escape (@eregon).
16+
* Handle a new variable inside the `case` target expression correctly (#3377, @eregon).
1617

1718
Compatibility:
1819

spec/ruby/language/case_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,22 @@ def ===(o)
399399
:called
400400
end.should == :called
401401
end
402+
403+
it "supports declaring variables in the case target expression" do
404+
def test(v)
405+
case new_variable_in_expression = v
406+
when true
407+
# This extra block is a test that `new_variable_in_expression` is declared outside of it and not inside
408+
self.then { new_variable_in_expression }
409+
else
410+
# Same
411+
self.then { new_variable_in_expression.casecmp?("foo") }
412+
end
413+
end
414+
415+
self.test("bar").should == false
416+
self.test(true).should == true
417+
end
402418
end
403419

404420
describe "The 'case'-construct with no target expression" do

src/main/java/org/truffleruby/parser/BodyTranslator.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,8 +693,6 @@ protected ArgumentsAndBlockTranslation translateArgumentsAndBlock(SourceIndexLen
693693
public RubyNode visitCaseNode(CaseParseNode node) {
694694
final SourceIndexLength sourceSection = node.getPosition();
695695

696-
RubyNode elseNode = translateNodeOrNil(sourceSection, node.getElseNode());
697-
698696
/* There are two sorts of case - one compares a list of expressions against a value, the other just checks a
699697
* list of expressions for truth. */
700698

@@ -710,6 +708,8 @@ public RubyNode visitCaseNode(CaseParseNode node) {
710708
/* Build an if expression from the whens and else. Work backwards because the first if contains all the
711709
* others in its else clause. */
712710

711+
RubyNode elseNode = translateNodeOrNil(sourceSection, node.getElseNode());
712+
713713
for (int n = node.getCases().size() - 1; n >= 0; n--) {
714714
final WhenParseNode when = (WhenParseNode) node.getCases().get(n);
715715

@@ -746,6 +746,8 @@ public RubyNode visitCaseNode(CaseParseNode node) {
746746
// A top-level block assigns the temp then runs the if
747747
ret = sequence(sourceSection, Arrays.asList(assignTemp, ifNode));
748748
} else {
749+
RubyNode elseNode = translateNodeOrNil(sourceSection, node.getElseNode());
750+
749751
for (int n = node.getCases().size() - 1; n >= 0; n--) {
750752
final WhenParseNode when = (WhenParseNode) node.getCases().get(n);
751753

src/main/java/org/truffleruby/parser/YARPTranslator.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,6 @@ public RubyNode visitCaseNode(Nodes.CaseNode node) {
865865
// - the other just checks a list of expressions for truth.
866866

867867
final RubyNode rubyNode;
868-
RubyNode elseNode = translateNodeOrNil(node.consequent);
869868

870869
if (node.predicate != null) {
871870
// Evaluate the case expression and store it in a local
@@ -875,6 +874,8 @@ public RubyNode visitCaseNode(Nodes.CaseNode node) {
875874

876875
// Build an if expression from `when` and `else` branches.
877876
// Work backwards to make the first if contain all the others in its `else` clause.
877+
RubyNode elseNode = translateNodeOrNil(node.consequent);
878+
878879
final Nodes.Node[] conditions = node.conditions;
879880

880881
for (int n = conditions.length - 1; n >= 0; n--) {
@@ -936,6 +937,8 @@ public RubyNode visitCaseNode(Nodes.CaseNode node) {
936937
// Build an if expression from `when` and `else` branches.
937938
// Work backwards to make the first if contain all the others in its `else` clause.
938939

940+
RubyNode elseNode = translateNodeOrNil(node.consequent);
941+
939942
final Nodes.Node[] conditions = node.conditions;
940943

941944
for (int n = node.conditions.length - 1; n >= 0; n--) {

0 commit comments

Comments
 (0)