Bug #21540
closed
prism allows `foo && return bar` when parse.y doesn't
Description
Code such as foo && return bar
has been disallowed in ruby since at least Ruby 2.0. Prism allows it though:
$ ruby -cve "a && return foo"
ruby 3.5.0dev (2025-08-08T02:57:23Z master 3ad26d0501) +PRISM [x86_64-linux]
Syntax OK
$ ruby --parser=parse.y -cve "a && return foo"
ruby 3.5.0dev (2025-08-08T02:57:23Z master 3ad26d0501) [x86_64-linux]
-e:1: syntax error, unexpected local variable or method, expecting end-of-input
a && return foo
ruby: compile error (SyntaxError)
The code seems to behave like I'd expect it to and I wouldn't mind it being accepted but it is inconsistent. Also happens on Ruby 3.4
Updated by nobu (Nobuyoshi Nakada) about 1 month ago
It is because of the precedence, and has been since 1.x at least.
Updated by nobu (Nobuyoshi Nakada) about 1 month ago
- Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.2: DONTNEED, 3.3: DONTNEED, 3.4: REQUIRED
Updated by Earlopain (Earlopain _) about 1 month ago
Right, I understand. foo && (return bar)
would be allowed, thanks for clarifying (works as expected in prism and parse.y)
Updated by naruse (Yui NARUSE) 25 days ago
- Status changed from Open to Assigned
- Assignee set to prism
Updated by Eregon (Benoit Daloze) 24 days ago
ยท Edited
Given it's ruby: compile error (SyntaxError)
from parse.y I guess it's a check done in compile.c
and missing in prism_compile.c
, if so it's not an issue in the parser itself but in the validation done by the bytecode compiler.
Updated by Earlopain (Earlopain _) 23 days ago
That's just how parse.y shows its syntax errors in general, you can check with any other syntax error. -c
doesn't involve the compiler.
Anyways, if it was done in the compiler then other implementations would need to handle it as well and consumers of prism can successfully parse code that ruby would otherwise reject at runtime with a syntax error.
Updated by Eregon (Benoit Daloze) 23 days ago
Indeed, you're right:
Thread 1 "ruby" hit Breakpoint 1, syntax_error_initialize (argc=0, argv=0x0, self=140736655388480) at error.c:2943
warning: 2943 error.c: No such file or directory
(gdb) bt
#0 syntax_error_initialize (argc=0, argv=0x0, self=140736655388480) at error.c:2943
#1 0x00007ffff7af993b in vm_call0_cfunc_with_frame (ec=0x40dd00, calling=0x7fffffffbee0, argv=0x0) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/vm_eval.c:164
#2 vm_call0_cfunc (ec=0x40dd00, calling=0x7fffffffbee0, argv=0x0) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/vm_eval.c:178
#3 vm_call0_body (ec=ec@entry=0x40dd00, calling=calling@entry=0x7fffffffc030, argv=argv@entry=0x0) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/vm_eval.c:229
#4 0x00007ffff7afe534 in vm_call0_cc (ec=0x40dd00, recv=140736655388480, id=3169, argc=0, argv=0x0, cc=0x7fffce59ef18, kw_splat=<optimized out>) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/vm_eval.c:101
#5 rb_call0 (ec=0x40dd00, recv=recv@entry=140736655388480, mid=mid@entry=3169, argc=argc@entry=0, argv=argv@entry=0x0, call_scope=call_scope@entry=CALL_FCALL, self=140737353010600) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/vm_eval.c:554
#6 0x00007ffff7afefb2 in rb_call (recv=140736655388480, mid=3169, argc=0, argv=0x0, scope=CALL_FCALL) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/vm_eval.c:873
#7 rb_funcallv_kw (recv=recv@entry=140736655388480, mid=mid@entry=3169, argc=argc@entry=0, argv=argv@entry=0x0, kw_splat=kw_splat@entry=0) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/vm_eval.c:1070
#8 0x00007ffff78f2a1f in rb_obj_call_init_kw (obj=obj@entry=140736655388480, argc=argc@entry=0, argv=argv@entry=0x0, kw_splat=kw_splat@entry=0) at eval.c:1752
#9 0x00007ffff799378d in rb_class_new_instance_kw (argc=0, argv=0x0, klass=140737353079040, kw_splat=kw_splat@entry=0) at object.c:2191
#10 0x00007ffff79937b7 in rb_class_new_instance (argc=<optimized out>, argv=<optimized out>, klass=<optimized out>) at object.c:2199
#11 0x00007ffff79d1361 in syntax_error_new () at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/parse.y:75
#12 yycompile0 (arg=arg@entry=4958656) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/parse.y:7558
#13 0x00007ffff7b0ffbd in rb_suppress_tracing (func=func@entry=0x7ffff79d1060 <yycompile0>, arg=arg@entry=4958656) at vm_trace.c:487
#14 0x00007ffff79ac10f in yycompile (p=0x4ba9c0, fname=<optimized out>, line=1) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/parse.y:7604
#15 rb_parser_compile (p=0x4ba9c0, gets=gets@entry=0x7ffff7a42860 <lex_get_str>, fname=fname@entry=140736655388760, input=input@entry=0x4bac10, line=line@entry=1) at /tmp/ruby-build.20250215124933.32308.uR2rR3/ruby-3.4.2/parse.y:7644
#16 0x00007ffff7a42b5c in parser_compile (p=<optimized out>, gets=0x7ffff7a42860 <lex_get_str>, fname=140736655388760, input=0x4bac10, line=1) at ruby_parser.c:649
#17 parser_compile_string0 (parser=0x4bac00, fname=140736655388760, s=140736685089480, line=1) at ruby_parser.c:663
#18 parser_compile_string_path (parser=0x4bac00, f=140736655388760, s=140736685089480, line=1) at ruby_parser.c:680
#19 parser_compile_string (parser=0x4bac00, f=<optimized out>, s=140736685089480, line=1) at ruby_parser.c:686
#20 rb_parser_compile_string (vparser=<optimized out>, vparser@entry=140736655388880, f=<optimized out>, s=140736685089480, line=line@entry=1) at ruby_parser.c:812
#21 0x00007ffff7a41186 in process_script (opt=0x7fffffffd850) at ruby.c:2094
#22 process_options (argc=0, argc@entry=4, argv=0x7fffffffdb68, argv@entry=0x7fffffffdb48, opt=opt@entry=0x7fffffffd850) at ruby.c:2534
#23 0x00007ffff7a41e7e in ruby_process_options (argc=argc@entry=4, argv=argv@entry=0x7fffffffdb48) at ruby.c:228
#24 0x00007ffff78f1e48 in ruby_options (argc=argc@entry=4, argv=argv@entry=0x7fffffffdb48) at eval.c:117
#25 0x00000000004010f8 in rb_main (argc=4, argv=0x7fffffffdb48) at ./main.c:43
#26 main (argc=<optimized out>, argv=<optimized out>) at ./main.c:68
And syntax_error_initialize
defaults to "compile error"
if there is no message, that's quite confusing, I assumed "compile error" to mean "error while compiling to bytecode".
Updated by Earlopain (Earlopain _) 15 days ago
I got a PR https://github.com/ruby/prism/pull/3630 that aims to fix this.
Updated by naruse (Yui NARUSE) 2 days ago
@prism This issue breaks Ruby's compatibility. This should be fixed before Ruby 3.5 (or 4.0) is released. But this issue looks not worked even if there is a PR. I worried that prism is now well maintained or not. As release manager, I also worried this situation is not enough healthy for Ruby 3.5. Could you handle prism issues?
Updated by kddnewton (Kevin Newton) 2 days ago
I will make a PR for this as soon as possible to get it ready for the 3.5 release.
Updated by kddnewton (Kevin Newton) 2 days ago
- Status changed from Assigned to Closed
Thanks to @Earlopain this is now done. https://github.com/ruby/prism/pull/3630