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

Make circular argument reference a SyntaxError instead of a warning

Fixes [Bug #10314]
This commit is contained in:
Jeremy Evans 2019-08-11 16:22:58 -07:00
parent fdfb5100b9
commit 0162e7e647
Notes: git 2019-10-18 01:32:31 +09:00
5 changed files with 99 additions and 54 deletions

View file

@ -9890,7 +9890,8 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc)
if (dyna_in_block(p) && dvar_defined_ref(p, id, &vidp)) { if (dyna_in_block(p) && dvar_defined_ref(p, id, &vidp)) {
if (NUMPARAM_ID_P(id) && numparam_nested_p(p)) return 0; if (NUMPARAM_ID_P(id) && numparam_nested_p(p)) return 0;
if (id == p->cur_arg) { if (id == p->cur_arg) {
rb_warn1("circular argument reference - %"PRIsWARN, rb_id2str(id)); compile_error(p, "circular argument reference - %"PRIsWARN, rb_id2str(id));
return 0;
} }
if (vidp) *vidp |= LVAR_USED; if (vidp) *vidp |= LVAR_USED;
node = NEW_DVAR(id, loc); node = NEW_DVAR(id, loc);
@ -9898,7 +9899,8 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc)
} }
if (local_id_ref(p, id, &vidp)) { if (local_id_ref(p, id, &vidp)) {
if (id == p->cur_arg) { if (id == p->cur_arg) {
rb_warn1("circular argument reference - %"PRIsWARN, rb_id2str(id)); compile_error(p, "circular argument reference - %"PRIsWARN, rb_id2str(id));
return 0;
} }
if (vidp) *vidp |= LVAR_USED; if (vidp) *vidp |= LVAR_USED;
node = NEW_LVAR(id, loc); node = NEW_LVAR(id, loc);

View file

@ -876,7 +876,8 @@ describe "Post-args" do
end end
describe "with a circular argument reference" do describe "with a circular argument reference" do
it "shadows an existing local with the same name as the argument" do ruby_version_is ''...'2.7' do
it "warns and uses a nil value when there is an existing local variable with same name" do
a = 1 a = 1
-> { -> {
@proc = eval "proc { |a=a| a }" @proc = eval "proc { |a=a| a }"
@ -884,13 +885,30 @@ describe "Post-args" do
@proc.call.should == nil @proc.call.should == nil
end end
it "shadows an existing method with the same name as the argument" do it "warns and uses a nil value when there is an existing method with same name" do
def a; 1; end def a; 1; end
-> { -> {
@proc = eval "proc { |a=a| a }" @proc = eval "proc { |a=a| a }"
}.should complain(/circular argument reference/) }.should complain(/circular argument reference/)
@proc.call.should == nil @proc.call.should == nil
end end
end
ruby_version_is '2.7' do
it "raises a SyntaxError if using an existing local with the same name as the argument" do
a = 1
-> {
@proc = eval "proc { |a=a| a }"
}.should raise_error(SyntaxError)
end
it "raises a SyntaxError if there is an existing method with the same name as the argument" do
def a; 1; end
-> {
@proc = eval "proc { |a=a| a }"
}.should raise_error(SyntaxError)
end
end
it "calls an existing method with the same name as the argument if explicitly using ()" do it "calls an existing method with the same name as the argument if explicitly using ()" do
def a; 1; end def a; 1; end

View file

@ -177,7 +177,8 @@ describe "An instance method with a default argument" do
foo(2,3,3).should == [2,3,[3]] foo(2,3,3).should == [2,3,[3]]
end end
it "shadows an existing method with the same name as the local" do ruby_version_is ''...'2.7' do
it "warns and uses a nil value when there is an existing local method with same name" do
def bar def bar
1 1
end end
@ -189,6 +190,20 @@ describe "An instance method with a default argument" do
foo.should == nil foo.should == nil
foo(2).should == 2 foo(2).should == 2
end end
end
ruby_version_is '2.7' do
it "raises a syntaxError an existing method with the same name as the local variable" do
def bar
1
end
-> {
eval "def foo(bar = bar)
bar
end"
}.should raise_error(SyntaxError)
end
end
it "calls a method with the same name as the local when explicitly using ()" do it "calls a method with the same name as the local when explicitly using ()" do
def bar def bar

View file

@ -267,7 +267,8 @@ describe "A lambda literal -> () { }" do
end end
describe "with circular optional argument reference" do describe "with circular optional argument reference" do
it "shadows an existing local with the same name as the argument" do ruby_version_is ''...'2.7' do
it "warns and uses a nil value when there is an existing local variable with same name" do
a = 1 a = 1
-> { -> {
@proc = eval "-> (a=a) { a }" @proc = eval "-> (a=a) { a }"
@ -275,13 +276,30 @@ describe "A lambda literal -> () { }" do
@proc.call.should == nil @proc.call.should == nil
end end
it "shadows an existing method with the same name as the argument" do it "warns and uses a nil value when there is an existing method with same name" do
def a; 1; end def a; 1; end
-> { -> {
@proc = eval "-> (a=a) { a }" @proc = eval "-> (a=a) { a }"
}.should complain(/circular argument reference/) }.should complain(/circular argument reference/)
@proc.call.should == nil @proc.call.should == nil
end end
end
ruby_version_is '2.7' do
it "raises a SyntaxError if using an existing local with the same name as the argument" do
a = 1
-> {
@proc = eval "-> (a=a) { a }"
}.should raise_error(SyntaxError)
end
it "raises a SyntaxError if there is an existing method with the same name as the argument" do
def a; 1; end
-> {
@proc = eval "-> (a=a) { a }"
}.should raise_error(SyntaxError)
end
end
it "calls an existing method with the same name as the argument if explicitly using ()" do it "calls an existing method with the same name as the argument if explicitly using ()" do
def a; 1; end def a; 1; end

View file

@ -230,27 +230,23 @@ class TestSyntax < Test::Unit::TestCase
end end
def test_keyword_self_reference def test_keyword_self_reference
bug9593 = '[ruby-core:61299] [Bug #9593]'
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var: defined?(var)) var end") o.instance_eval("def foo(var: defined?(var)) var end")
end end
assert_equal(42, o.foo(var: 42))
assert_equal("local-variable", o.foo, bug9593)
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var: var) var end") o.instance_eval("def foo(var: var) var end")
end end
assert_nil(o.foo, bug9593)
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var: bar(var)) var end") o.instance_eval("def foo(var: bar(var)) var end")
end end
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var: bar {var}) var end") o.instance_eval("def foo(var: bar {var}) var end")
end end
@ -302,37 +298,33 @@ class TestSyntax < Test::Unit::TestCase
end end
def test_optional_self_reference def test_optional_self_reference
bug9593 = '[ruby-core:61299] [Bug #9593]'
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var = defined?(var)) var end") o.instance_eval("def foo(var = defined?(var)) var end")
end end
assert_equal(42, o.foo(42))
assert_equal("local-variable", o.foo, bug9593)
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var = var) var end") o.instance_eval("def foo(var = var) var end")
end end
assert_nil(o.foo, bug9593)
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var = bar(var)) var end") o.instance_eval("def foo(var = bar(var)) var end")
end end
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var = bar {var}) var end") o.instance_eval("def foo(var = bar {var}) var end")
end end
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var = (def bar;end; var)) var end") o.instance_eval("def foo(var = (def bar;end; var)) var end")
end end
o = Object.new o = Object.new
assert_warn(/circular argument reference - var/) do assert_raise(SyntaxError) do
o.instance_eval("def foo(var = (def self.bar;end; var)) var end") o.instance_eval("def foo(var = (def self.bar;end; var)) var end")
end end