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:
parent
ea32715e00
commit
7a288df7b8
Notes:
git
2020-02-12 05:44:46 +09:00
5 changed files with 29 additions and 21 deletions
2
NEWS.md
2
NEWS.md
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
13
compile.c
13
compile.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue