Skip to content

Commit

Permalink
Treat return in block in class/module as LocalJumpError (#2511)
Browse files Browse the repository at this point in the history
return directly in class/module is an error, so return in
proc in class/module should also be an error.  I believe the
previous behavior was an unintentional oversight during the
addition of top-level return in 2.4.
  • Loading branch information
jeremyevans committed Oct 2, 2019
1 parent 9759e3c commit ef69738
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 11 deletions.
21 changes: 11 additions & 10 deletions spec/ruby/language/return_spec.rb
Expand Up @@ -443,17 +443,18 @@ class ReturnSpecs::A
end

describe "within a block within a class" do
it "is allowed" do
File.write(@filename, <<-END_OF_CODE)
class ReturnSpecs::A
ScratchPad << "before return"
1.times { return }
ScratchPad << "after return"
end
END_OF_CODE
ruby_version_is "2.7" do
it "is not allowed" do
File.write(@filename, <<-END_OF_CODE)
class ReturnSpecs::A
ScratchPad << "before return"
1.times { return }
ScratchPad << "after return"
end
END_OF_CODE

load @filename
ScratchPad.recorded.should == ["before return"]
-> { load @filename }.should raise_error(LocalJumpError)
end
end
end

Expand Down
4 changes: 4 additions & 0 deletions test/ruby/test_syntax.rb
Expand Up @@ -1272,6 +1272,10 @@ def test_return_toplevel_with_argument
assert_warn(/argument of top-level return is ignored/) {eval("return 1")}
end

def test_return_in_proc_in_class
assert_in_out_err(['-e', 'class TestSyntax; proc{ return }.call; end'], "", [], /^-e:1:.*unexpected return \(LocalJumpError\)/)
end

def test_syntax_error_in_rescue
bug12613 = '[ruby-core:76531] [Bug #12613]'
assert_syntax_error("#{<<-"begin;"}\n#{<<-"end;"}", /Invalid retry/, bug12613)
Expand Down
6 changes: 5 additions & 1 deletion vm_insnhelper.c
Expand Up @@ -1258,7 +1258,10 @@ vm_throw_start(const rb_execution_context_t *ec, rb_control_frame_t *const reg_c
switch (escape_cfp->iseq->body->type) {
case ISEQ_TYPE_TOP:
case ISEQ_TYPE_MAIN:
if (toplevel) goto valid_return;
if (toplevel) {
if (in_class_frame) goto unexpected_return;
goto valid_return;
}
break;
case ISEQ_TYPE_EVAL:
case ISEQ_TYPE_CLASS:
Expand All @@ -1276,6 +1279,7 @@ vm_throw_start(const rb_execution_context_t *ec, rb_control_frame_t *const reg_c

escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
}
unexpected_return:;
rb_vm_localjump_error("unexpected return", throwobj, TAG_RETURN);

valid_return:;
Expand Down

0 comments on commit ef69738

Please sign in to comment.