Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected return (LocalJumpError) #2438

Open
gogainda opened this issue Sep 3, 2021 · 6 comments
Open

Unexpected return (LocalJumpError) #2438

gogainda opened this issue Sep 3, 2021 · 6 comments

Comments

@gogainda
Copy link
Contributor

gogainda commented Sep 3, 2021

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

@eregon
Copy link
Member

eregon commented Sep 6, 2021

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.

@eregon
Copy link
Member

eregon commented May 13, 2022

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.

@eregon
Copy link
Member

eregon commented May 13, 2022

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)

@eregon
Copy link
Member

eregon commented Jul 24, 2023

When we implement this we should reenable rdoc CI: ruby/rdoc#1029

@eregon
Copy link
Member

eregon commented Jul 26, 2023

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 return in BEGIN {} in eval specially, and always use a LocalReturnException.

@eregon
Copy link
Member

eregon commented Jul 26, 2023

ruby/rdoc#1032 so rdoc uses the more portable pattern eval("BEGIN { throw :valid, true }\n#{code}")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants