From 1cbe114d1cf57dc47b4bbc6780f424647dd906d9 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Fri, 8 Dec 2023 15:00:48 -0500 Subject: [PRISM] Fix `PM_CALL_NODE` assignment This PR fixes ruby/prism#1963. Array and variable assignment was broken for call nodes. The change checks if the `method_id` is related to assignment and if is adds a `putnil`, `setn` and a `pop`. The incorrect instructions meant that in some cases (demonstrated in tests) the wrong value would be returned. I verified that this fixes the test mentioned in the issue (run: `RUBY_ISEQ_DUMP_DEBUG=prism make test/-ext-/st/test_numhash.rb`) Incorrect instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(4,10)> 0000 putnil ( 4)[Li] 0001 putself 0002 send , nil 0005 putself 0006 send , nil 0009 putself 0010 send , nil 0013 setn 3 0015 send , nil 0018 pop 0019 leave "********* PRISM *************" == disasm: #@:3 (3,0)-(3,10)> 0000 putself ( 3)[Li] 0001 send , nil 0004 putself 0005 send , nil 0008 putself 0009 send , nil 0012 send , nil 0015 leave ``` Fixed instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(4,10)> 0000 putnil ( 4)[Li] 0001 putself 0002 send , nil 0005 putself 0006 send , nil 0009 putself 0010 send , nil 0013 setn 3 0015 send , nil 0018 pop 0019 leave "********* PRISM *************" == disasm: #@:3 (3,0)-(3,10)> 0000 putnil ( 3)[Li] 0001 putself 0002 send , nil 0005 putself 0006 send , nil 0009 putself 0010 send , nil 0013 setn 3 0015 send , nil 0018 pop 0019 leave ``` Fixes ruby/prism#1963 --- test/ruby/test_compile_prism.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'test/ruby') diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 3d7e16a59a..c2cb60251c 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1301,6 +1301,34 @@ module Prism CODE assert_prism_eval("prism_test_call_node_splat(*[], 1, 2)") + + assert_prism_eval(<<-CODE) + class Foo + def []=(a, b) + 1234 + end + end + + def self.foo(i, j) + tbl = Foo.new + tbl[i] = j + end + foo(1, 2) + CODE + + assert_prism_eval(<<-CODE) + class Foo + def i=(a) + 1234 + end + end + + def self.foo(j) + tbl = Foo.new + tbl.i = j + end + foo(1) + CODE end def test_CallAndWriteNode -- cgit v1.2.3