diff --git a/lib/natalie/compiler/args.rb b/lib/natalie/compiler/args.rb index aee4fe002..108b1252a 100644 --- a/lib/natalie/compiler/args.rb +++ b/lib/natalie/compiler/args.rb @@ -168,7 +168,7 @@ def transform_optional_arg(arg) default_value = arg.value if default_value&.type == :local_variable_read_node && default_value.name == name - raise SyntaxError, "circular argument reference - #{name}" + default_value = Prism.nil_node(location: default_value.location) end @instructions << ArrayIsEmptyInstruction.new diff --git a/spec/language/block_spec.rb b/spec/language/block_spec.rb index 6248a8933..9585acb94 100644 --- a/spec/language/block_spec.rb +++ b/spec/language/block_spec.rb @@ -979,27 +979,39 @@ def obj.to_ary; raise "Exception raised in #to_ary" end end.call(2, 3).should == [2, 6, [], 3] end - # NATFIXME: circular argument reference - a describe "with a circular argument reference" do - xit "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 + ruby_version_is ""..."3.4" do + it "raises a SyntaxError if using the argument in its default value" do + NATFIXME 'We implement the Ruby 3.4 behaviour' do + a = 1 + -> { + eval "proc { |a=a| a }" + }.should raise_error(SyntaxError) + end + + NATFIXME "Restore this part of the spec once we've moved to Ruby 3.4 compatibility" do + RUBY_VERSION.should.start_with?('3.4.') + end - xit "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) + -> { + eval "proc { |a=a| a }.call" + }.call.should == nil + end end - it "calls an existing method with the same name as the argument if explicitly using ()" do - def a; 1; end - proc { |a=a()| a }.call.should == 1 + ruby_version_is "3.4" do + it "is nil if using the argument in its default value" do + -> { + eval "proc { |a=a| a }.call" + }.call.should == nil + end end end + + it "calls an existing method with the same name as the argument if explicitly using ()" do + def a; 1; end + proc { |a=a()| a }.call.should == 1 + end end describe "with pattern matching" do diff --git a/test/natalie/method_test.rb b/test/natalie/method_test.rb index d90b78e8c..a18a3717a 100644 --- a/test/natalie/method_test.rb +++ b/test/natalie/method_test.rb @@ -201,8 +201,8 @@ def yield_to_block(&b) default_nils.should == [nil, nil] default_nils(1).should == [1, nil] default_nils(1, 2).should == [1, 2] - out = `bin/natalie -e "def circular_argument_reference(a = a); a; end" 2>&1` - out.should =~ /parameter default value references itself|circular argument reference - a/ + out = `bin/natalie -e "def circular_argument_reference(a = a); p a; end; circular_argument_reference" 2>&1` + out.should =~ /^nil$/ end def default_first1(x = 1)