truffleruby
truffleruby copied to clipboard
`break` causes `BreakException` to escape out of the interpreter
This seems to trigger on the latest 21.1.0 stable, as well as on a recent nightly:
$ ruby -e "puts RUBY_DESCRIPTION; break"
truffleruby 21.3.0-dev-e1c70780, like ruby 2.7.3, GraalVM CE Native [x86_64-linux]
truffleruby: an internal exception escaped out of the interpreter,
please report it to https://github.com/oracle/truffleruby/issues.
```
<no message> (org.truffleruby.language.control.BreakException)
```
On CRuby it's:
$ ruby -e "puts RUBY_DESCRIPTION; break" |& cat
-e:1: Invalid break
-e: compile error (SyntaxError)
So probably something to handle in the parser or translator.
Such code is always incorrect of course, is some variant of it used in some gem or app?
I half-wrote a spec but then got de-motivated when I saw I'd have to work on the parser.
diff --git a/spec/ruby/language/fixtures/break_toplevel.rb b/spec/ruby/language/fixtures/break_toplevel.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aacc9e7a452d1fbdda42e485b1fa174556d96002
--- /dev/null
+++ b/spec/ruby/language/fixtures/break_toplevel.rb
@@ -0,0 +1 @@
+break "break"
diff --git a/spec/ruby/language/break_spec.rb b/spec/ruby/language/break_spec.rb
index 627cb4a071fca414ba2aec4a77088fdbd8f99935..b75403ee85531c36c24958bc42f7bab66d4494de 100644
--- a/spec/ruby/language/break_spec.rb
+++ b/spec/ruby/language/break_spec.rb
@@ -252,6 +252,12 @@ describe "Break inside a while loop" do
end
end
+describe "Break from the toplevel" do
+ it "is a compile error" do
+ code = fixture __FILE__, "break_toplevel.rb"
+ ruby_exe(code, exit_status: 1, args: "2>&1").should =~ /compile error (SyntaxError)/
+ end
+end
# TODO: Rewrite all the specs from here to the end of the file in the style
# above.
Such code is always incorrect of course, is some variant of it used in some gem or app?
Indeed, I can provide a bit more context. I usually have pry-byebug
or a similar one installed, which provides a break
command (for listing breakpoints).
I forgot that under TruffleRuby it doesn't work, so I just typed break
inside the REPL and my app died with that error:
[1] pry(main)> break
truffleruby: an internal exception escaped out of the interpreter,
please report it to https://github.com/oracle/truffleruby/issues.
whereas in MRI if I uninstall the debugging gem I get an error, but my app doesn't die:
[1] pry(main)> break
(eval):2: Can't escape from eval with break
[1] pry(main)>
So I thought it'd be nice to report it, so that a "oops explosion VM died" could be replaced with a "dear user, what you asked made no sense" :)
That's a slightly different case actually.
It seems break
is actually forbidden in eval
, be it a break-from-call-with-block or a break-from-while:
$ ruby -e 'self.then { eval "break" }'
Traceback (most recent call last):
(eval): (eval):1: Can't escape from eval with break (SyntaxError)
$ ruby -e 'while true; eval "break 42"; end'
Traceback (most recent call last):
(eval): (eval):1: Can't escape from eval with break (SyntaxError)
Probably it is easier to handle this in the BodyTranslator, e.g., see if it's a top-level or eval ParserContext, and there is no block or while
around it. Probably need to check if there is no parent MethodTranslator or so.
Note: https://github.com/oracle/truffleruby/issues/1672#issuecomment-797446928 is the issue with pry-byebug
.
The issue seems already fixed (on master):
$ jt -q ruby -ve "puts RUBY_DESCRIPTION; break"
truffleruby 24.1.0-dev-2651959c*, like ruby 3.2.2, Interpreted JVM [x86_64-darwin]
truffleruby: -e:1: Invalid break (SyntaxError)