Bug #22448
openJump value with a command call with a method call chained
Description
This is a little bit odd, found this while fuzzing Prism.
Right now, parse.y raises a void value expression error for a method call on a parenthesized jump, as in:
but if you get rid of the parentheses it says it's good to go, and compiles unreachable code:
$ ruby --parser=parse.y --dump=insns -e 'def m; return foo 1 do end.bar; end'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,35)>
0000 definemethod :m, m ( 1)[Li]
0003 putobject :m
0005 leave
== disasm: #<ISeq:m@-e:1 (1,0)-(1,35)>
0000 putself ( 1)[LiCa]
0001 putobject_INT2FIX_1_
0002 send <calldata!mid:foo, argc:1, FCALL>, block in m
0005 leave [Re]
0006 putnil
0007 opt_send_without_block <calldata!mid:bar, argc:0, ARGS_SIMPLE>
0009 leave [Re]
== disasm: #<ISeq:block in m@-e:1 (1,20)-(1,26)>
0000 putnil ( 1)[Bc]
0001 leave [Br]
The parse tree actually attaches the block to the return itself. The same thing happens with break and next, with ., &. and ::, and with arguments on the chained call:
$ ruby --parser=parse.y -ce 'loop { break foo 1 do end.bar }' # Syntax OK
$ ruby --parser=parse.y -ce 'loop { next foo 1 do end.bar }' # Syntax OK
$ ruby --parser=parse.y -ce 'def m; return foo 1 do end&.bar; end' # Syntax OK
$ ruby --parser=parse.y -ce 'def m; return foo 1 do end::bar; end' # Syntax OK
$ ruby --parser=parse.y -ce 'def m; return foo 1 do end.bar 2; end' # Syntax OK
$ ruby --parser=parse.y -ce 'loop { (break foo do end).bar }' # void value expression
I think all of these should be void value expressions since they're just compiling dead code.
For context, Prism has been parsing those chains within the jump, so they get called before their result is thrown, which is inconsistent. So we could also just do that in parse.y instead. I'm fine with either solution.
No data to display