ruby-changes:58087
From: Jeremy <ko1@a...>
Date: Wed, 2 Oct 2019 23:56:50 +0900 (JST)
Subject: [ruby-changes:58087] ef697388be (master): Treat return in block in class/module as LocalJumpError (#2511)
https://git.ruby-lang.org/ruby.git/commit/?id=ef697388be From ef697388becedf36966a2edcdcf88baca342b9e2 Mon Sep 17 00:00:00 2001 From: Jeremy Evans <code@j...> Date: Wed, 2 Oct 2019 07:56:28 -0700 Subject: 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. diff --git a/spec/ruby/language/return_spec.rb b/spec/ruby/language/return_spec.rb index 7f740be..7eef6d0 100644 --- a/spec/ruby/language/return_spec.rb +++ b/spec/ruby/language/return_spec.rb @@ -443,17 +443,18 @@ describe "The return keyword" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/language/return_spec.rb#L443 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 a64d258..80bff86 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1272,6 +1272,10 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1272 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 76bc56d..ef5a6db 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 https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1258 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 https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1279 escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp); } + unexpected_return:; rb_vm_localjump_error("unexpected return", throwobj, TAG_RETURN); valid_return:; -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/