diff options
author | Jeremy Evans <code@jeremyevans.net> | 2019-10-02 07:56:28 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-02 07:56:28 -0700 |
commit | ef697388becedf36966a2edcdcf88baca342b9e2 (patch) | |
tree | 816a19ad728f795d71402db947386e7e9dfb6226 | |
parent | 9759e3c9f09ec442b2aa0d0cc299ac791e516a01 (diff) | |
download | ruby-ef697388becedf36966a2edcdcf88baca342b9e2.tar.gz |
Treat return in block in class/module as LocalJumpError (#2511)
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.
-rw-r--r-- | spec/ruby/language/return_spec.rb | 21 | ||||
-rw-r--r-- | test/ruby/test_syntax.rb | 4 | ||||
-rw-r--r-- | vm_insnhelper.c | 6 |
3 files changed, 20 insertions, 11 deletions
diff --git a/spec/ruby/language/return_spec.rb b/spec/ruby/language/return_spec.rb index 7f740be25b..7eef6d06ca 100644 --- a/spec/ruby/language/return_spec.rb +++ b/spec/ruby/language/return_spec.rb @@ -443,17 +443,18 @@ describe "The return keyword" do 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 diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index a64d25845a..80bff868f6 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1272,6 +1272,10 @@ eom 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) diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 76bc56d316..ef5a6db1af 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -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: @@ -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:; |