truffleruby
truffleruby copied to clipboard
Unexpected return (LocalJumpError)
throws an exception - unexpected return (LocalJumpError)
text = "not_ruby"
def parseable? text
verbose, $VERBOSE = $VERBOSE, nil
eval("BEGIN {return true}\n#{text}")
rescue SyntaxError
false
ensure
$VERBOSE = verbose
end
content = if parseable? text then
"parseable"
end
puts content
suprisingly MRI Ruby returns parseable which is obviously not
The code about is simplified version of this https://github.com/ruby/rdoc/blob/master/lib/rdoc/markup/to_html.rb#L214
Interesting, RDoc uses yet another variant to check if it's valid Ruby syntax: https://github.com/ruby/rdoc/blob/2f7dfecdc3c90477e2f77e8cbadfba9cbe444814/lib/rdoc/markup/to_html.rb#L427-L434 This is what IRB uses now: https://github.com/ruby/irb/pull/134/files/5eb3ef3293a026e3f7de1711b8a399fe736bdb13#r702901657
So this issue is about supporting return in BEGIN {} in eval, or maybe simply return in eval, which I think returns from the parseable? method, not just from the eval.
This also happens in bundle exec rake --trace doc of https://github.com/msgpack/msgpack-ruby/runs/6416790321?check_suite_focus=true:
$ bundle exec rake --trace doc
** Invoke doc (first_time)
** Execute doc
[warn]: @param tag has unknown parameter name: obj
in file `doclib/msgpack/factory.rb' near line 141
rake aborted!
LocalJumpError: unexpected return
(eval):1:in `parseable?'
/home/eregon/.rubies/truffleruby-dev/lib/mri/rdoc/markup/to_html.rb:429:in `parseable?'
/home/eregon/.rubies/truffleruby-dev/lib/mri/rdoc/markup/to_html.rb:214:in `accept_verbatim'
/home/eregon/.rubies/truffleruby-dev/lib/mri/rdoc/markup/verbatim.rb:26:in `accept'
/home/eregon/.rubies/truffleruby-dev/lib/mri/rdoc/markup/formatter.rb:75:in `block in accept_document'
/home/eregon/.rubies/truffleruby-dev/lib/mri/rdoc/markup/formatter.rb:70:in `each'
/home/eregon/.rubies/truffleruby-dev/lib/mri/rdoc/markup/formatter.rb:70:in `accept_document'
/home/eregon/.rubies/truffleruby-dev/lib/mri/rdoc/markup/document.rb:68:in `accept'
/home/eregon/.rubies/truffleruby-dev/lib/mri/rdoc/markup.rb:822:in `convert'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/helpers/markup/rdoc_markup.rb:54:in `block in to_html'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/helpers/markup/rdoc_markup.rb:52:in `synchronize'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/helpers/markup/rdoc_markup.rb:52:in `to_html'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/helpers/html_helper.rb:95:in `html_markup_markdown'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/helpers/html_helper.rb:62:in `htmlify'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/templates/default/layout/html/setup.rb:67:in `diskfile'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:367:in `render_section'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:259:in `block (2 levels) in run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:256:in `each'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:256:in `block in run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:398:in `add_options'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:255:in `run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:277:in `block in yieldall'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:412:in `with_section'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:277:in `yieldall'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/templates/default/layout/html/layout.erb:21:in `_erb_cache_5'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:287:in `erb'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/templates/default/layout/html/setup.rb:62:in `layout'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:367:in `render_section'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:259:in `block (2 levels) in run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:256:in `each'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:256:in `block in run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:398:in `add_options'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:255:in `run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:136:in `run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/templates/default/fulldoc/html/setup.rb:52:in `block in serialize_index'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/engine.rb:123:in `block in with_serializer'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/logging.rb:82:in `capture'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/engine.rb:121:in `with_serializer'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/templates/default/fulldoc/html/setup.rb:51:in `serialize_index'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/templates/default/fulldoc/html/setup.rb:68:in `serialize_file'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/templates/default/fulldoc/html/setup.rb:11:in `block in init'
<internal:core> core/enumerable.rb:355:in `each_with_index'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/templates/default/fulldoc/html/setup.rb:10:in `init'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:193:in `initialize'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:131:in `new'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/template.rb:136:in `run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/templates/engine.rb:105:in `generate'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/cli/yardoc.rb:357:in `run_generate'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/cli/yardoc.rb:267:in `run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/yard-0.9.27/lib/yard/rake/yardoc_task.rb:74:in `block in define'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/task.rb:281:in `block in execute'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/task.rb:281:in `each'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/task.rb:281:in `execute'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/home/eregon/.rubies/truffleruby-dev/lib/mri/monitor.rb:218:in `mon_synchronize'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/task.rb:188:in `invoke'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/application.rb:160:in `invoke_task'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/application.rb:116:in `each'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/application.rb:116:in `block in top_level'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/application.rb:125:in `run_with_threads'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/application.rb:110:in `top_level'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/application.rb:83:in `block in run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/lib/rake/application.rb:80:in `run'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/rake-13.0.6/exe/rake:27:in `<top (required)>'
<internal:core> core/kernel.rb:376:in `load'
<internal:core> core/kernel.rb:376:in `load'
/home/eregon/.rubies/truffleruby-dev/bin/rake:25:in `<top (required)>'
<internal:core> core/kernel.rb:376:in `load'
<internal:core> core/kernel.rb:376:in `load'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/cli/exec.rb:58:in `kernel_load'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/cli/exec.rb:23:in `run'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/cli.rb:478:in `exec'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/cli.rb:31:in `dispatch'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/cli.rb:25:in `start'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/bundler-2.2.32/libexec/bundle:49:in `block in <top (required)>'
/home/eregon/.rubies/truffleruby-dev/lib/mri/bundler/friendly_errors.rb:103:in `with_friendly_errors'
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/bundler-2.2.32/libexec/bundle:37:in `<top (required)>'
<internal:core> core/kernel.rb:376:in `load'
<internal:core> core/kernel.rb:376:in `load'
/home/eregon/.rubies/truffleruby-dev/bin/bundle:42:in `<main>'
Tasks: TOP => doc
Seems the exact same issue.
Some idea to fix this, we'd store the ReturnID in FrameDescriptor#getInfo(), and so when parsing the eval we could find the proper ReturnID to jump to.
Semantics are like (i.e., the return inside the eval returns to the surrounding method, and not allowed top-level):
$ ruby -e 'def m; eval "return 4*3"; p :after; end; p m'
12
$ ruby -e 'def m; proc { eval "return 4*3"; p :proc; }.call; p :after; end; p m'
12
$ ruby -e 'p eval "return 4*3"'
(eval):1:in `<main>': unexpected return (LocalJumpError)
When we implement this we should reenable rdoc CI: https://github.com/ruby/rdoc/pull/1029
Another idea, because it's quite complicated to store ReturnID for methods & lambda in FrameDescriptor without a lot of changes or performance impact:
- We could handle
returninBEGIN {}inevalspecially, and always use aLocalReturnException.
https://github.com/ruby/rdoc/pull/1032 so rdoc uses the more portable pattern eval("BEGIN { throw :valid, true }\n#{code}")