mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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.
This commit is contained in:
parent
9759e3c9f0
commit
ef697388be
Notes:
git
2019-10-02 23:56:57 +09:00
Merged-By: jeremyevans <code@jeremyevans.net>
3 changed files with 20 additions and 11 deletions
|
@ -443,17 +443,18 @@ describe "The return keyword" do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "within a block within a class" do
|
describe "within a block within a class" do
|
||||||
it "is allowed" do
|
ruby_version_is "2.7" do
|
||||||
File.write(@filename, <<-END_OF_CODE)
|
it "is not allowed" do
|
||||||
class ReturnSpecs::A
|
File.write(@filename, <<-END_OF_CODE)
|
||||||
ScratchPad << "before return"
|
class ReturnSpecs::A
|
||||||
1.times { return }
|
ScratchPad << "before return"
|
||||||
ScratchPad << "after return"
|
1.times { return }
|
||||||
end
|
ScratchPad << "after return"
|
||||||
END_OF_CODE
|
end
|
||||||
|
END_OF_CODE
|
||||||
|
|
||||||
load @filename
|
-> { load @filename }.should raise_error(LocalJumpError)
|
||||||
ScratchPad.recorded.should == ["before return"]
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1272,6 +1272,10 @@ eom
|
||||||
assert_warn(/argument of top-level return is ignored/) {eval("return 1")}
|
assert_warn(/argument of top-level return is ignored/) {eval("return 1")}
|
||||||
end
|
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
|
def test_syntax_error_in_rescue
|
||||||
bug12613 = '[ruby-core:76531] [Bug #12613]'
|
bug12613 = '[ruby-core:76531] [Bug #12613]'
|
||||||
assert_syntax_error("#{<<-"begin;"}\n#{<<-"end;"}", /Invalid retry/, bug12613)
|
assert_syntax_error("#{<<-"begin;"}\n#{<<-"end;"}", /Invalid retry/, bug12613)
|
||||||
|
|
|
@ -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) {
|
switch (escape_cfp->iseq->body->type) {
|
||||||
case ISEQ_TYPE_TOP:
|
case ISEQ_TYPE_TOP:
|
||||||
case ISEQ_TYPE_MAIN:
|
case ISEQ_TYPE_MAIN:
|
||||||
if (toplevel) goto valid_return;
|
if (toplevel) {
|
||||||
|
if (in_class_frame) goto unexpected_return;
|
||||||
|
goto valid_return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ISEQ_TYPE_EVAL:
|
case ISEQ_TYPE_EVAL:
|
||||||
case ISEQ_TYPE_CLASS:
|
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);
|
escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp);
|
||||||
}
|
}
|
||||||
|
unexpected_return:;
|
||||||
rb_vm_localjump_error("unexpected return", throwobj, TAG_RETURN);
|
rb_vm_localjump_error("unexpected return", throwobj, TAG_RETURN);
|
||||||
|
|
||||||
valid_return:;
|
valid_return:;
|
||||||
|
|
Loading…
Add table
Reference in a new issue