1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Make yield in singleton class definitions in methods a SyntaxError

This behavior was deprecated in 2.7 and scheduled to be removed
in 3.0.

Calling yield in a class definition outside a method is now a
SyntaxError instead of a LocalJumpError, as well.
This commit is contained in:
Jeremy Evans 2020-02-11 11:56:34 -08:00
parent ea32715e00
commit 7a288df7b8
Notes: git 2020-02-12 05:44:46 +09:00
5 changed files with 29 additions and 21 deletions

View file

@ -12,6 +12,8 @@ sufficient information, see the ChangeLog file or Redmine
* $SAFE is now a normal global variable with no special behavior. [Feature #16131] * $SAFE is now a normal global variable with no special behavior. [Feature #16131]
* yield in singleton class definitions in methods is now a SyntaxError. [Feature #15575]
## Command line options ## Command line options
## Core classes updates (outstanding ones only) ## Core classes updates (outstanding ones only)

View file

@ -296,14 +296,19 @@ assert_equal "true", %q{
s.return_eigenclass == class << s; self; end s.return_eigenclass == class << s; self; end
}, '[ruby-core:21379]' }, '[ruby-core:21379]'
assert_equal "true", %q{ assert_match %r{Invalid yield}, %q{
class Object STDERR.reopen(STDOUT)
def yield_eigenclass begin
class << self eval %q{
yield self class Object
def yield_eigenclass
class << self
yield self
end
end end
end end
end }
s = "foo" rescue SyntaxError => e
s.yield_eigenclass {|c| c == class << s; self; end } e.message
}, '[ruby-dev:40975]' end
}

View file

@ -7096,20 +7096,13 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *node, int poppe
} }
static int static int
check_yield_place(const rb_iseq_t *iseq, int line) check_yield_place(const rb_iseq_t *iseq)
{ {
VALUE file;
switch (iseq->body->local_iseq->body->type) { switch (iseq->body->local_iseq->body->type) {
case ISEQ_TYPE_TOP: case ISEQ_TYPE_TOP:
case ISEQ_TYPE_MAIN: case ISEQ_TYPE_MAIN:
return FALSE;
case ISEQ_TYPE_CLASS: case ISEQ_TYPE_CLASS:
file = rb_iseq_path(iseq); return FALSE;
if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) {
rb_compile_warn(RSTRING_PTR(file), line,
"`yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575]");
}
return TRUE;
default: default:
return TRUE; return TRUE;
} }
@ -7836,7 +7829,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
INIT_ANCHOR(args); INIT_ANCHOR(args);
if (check_yield_place(iseq, line) == FALSE) { if (check_yield_place(iseq) == FALSE) {
COMPILE_ERROR(ERROR_ARGS "Invalid yield"); COMPILE_ERROR(ERROR_ARGS "Invalid yield");
goto ng; goto ng;
} }

View file

@ -285,7 +285,7 @@ describe "A class definition extending an object (sclass)" do
}.should raise_error(TypeError) }.should raise_error(TypeError)
end end
ruby_version_is ""..."3.0" do ruby_version_is ""..."2.8" do
it "allows accessing the block of the original scope" do it "allows accessing the block of the original scope" do
suppress_warning do suppress_warning do
ClassSpecs.sclass_with_block { 123 }.should == 123 ClassSpecs.sclass_with_block { 123 }.should == 123
@ -293,6 +293,14 @@ describe "A class definition extending an object (sclass)" do
end end
end end
ruby_version_is "2.8" do
it "does not allow accessing the block of the original scope" do
-> {
ClassSpecs.sclass_with_block { 123 }
}.should raise_error(SyntaxError)
end
end
it "can use return to cause the enclosing method to return" do it "can use return to cause the enclosing method to return" do
ClassSpecs.sclass_with_return.should == :inner ClassSpecs.sclass_with_return.should == :inner
end end

View file

@ -312,7 +312,7 @@ class TestClass < Test::Unit::TestCase
end end
def test_invalid_yield_from_class_definition def test_invalid_yield_from_class_definition
assert_raise(LocalJumpError) { assert_raise(SyntaxError) {
EnvUtil.suppress_warning {eval("class C; yield; end")} EnvUtil.suppress_warning {eval("class C; yield; end")}
} }
end end