https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112020-08-06T11:00:32ZRuby Issue Tracking SystemRuby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=869572020-08-06T11:00:32ZEregon (Benoit Daloze)
<ul></ul><p>I should also note some of these semantics might significantly harm the performance of Ruby.<br>
CRuby seems to walk the stack on every <code>return</code>.<br>
On others VMs there need to be some extra logic to find if the frame to return to is still on the stack.<br>
It's already quite complicated but then if <code>return</code> can go to two places, it becomes a huge mess.</p> Ruby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=869592020-08-06T14:34:18ZHanmac (Hans Mackowiak)hanmac@gmx.de
<ul></ul><p>i think this is by design:</p>
<p><a href="https://www.rubyguides.com/2016/02/ruby-procs-and-lambdas/" class="external">https://www.rubyguides.com/2016/02/ruby-procs-and-lambdas/</a></p>
<blockquote>
<p>A lambda will return normally, like a regular method.<br>
But a proc will try to return from the current context.</p>
</blockquote>
<blockquote>
<p>Procs return from the current method, while lambdas return from the lambda itself.</p>
</blockquote> Ruby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=869602020-08-06T14:43:45Zchrisseaton (Chris Seaton)chris@chrisseaton.com
<ul></ul><p>Hans I don't think anyone is debating the basic idea of what return in a proc or lambda does - I think we're talking about the edge-case for a proc in a return in the example above, which isn't explained by the text you have.</p> Ruby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=869612020-08-06T19:09:44ZDan0042 (Daniel DeLorme)
<ul></ul><p>I think the behavior makes sense to some extent, because the proc is within 2 nested contexts. Since the proc is within the lambda context, calling it in the lambda returns from the lambda. And since the proc is <em>also</em> within the method context, calling it in the method returns from the method.</p>
<p>The <code>call_proc</code> branching logic makes this look more complicated than it really is, but if you separate the logic I feel the behavior is rather reasonable. What do you think should be the behavior of <code>m2</code> below?</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">m1</span>
<span class="n">r</span> <span class="o">=</span> <span class="o">-></span> <span class="p">{</span>
<span class="nb">proc</span> <span class="o">=</span> <span class="no">Proc</span><span class="p">.</span><span class="nf">new</span><span class="p">{</span> <span class="k">return</span> <span class="ss">:return</span> <span class="p">}</span>
<span class="nb">proc</span><span class="p">.</span><span class="nf">call</span> <span class="c1">#return from lambda</span>
<span class="ss">:after_in_lambda</span>
<span class="p">}.</span><span class="nf">call</span>
<span class="p">[</span><span class="ss">:after_in_method</span><span class="p">,</span> <span class="n">r</span><span class="p">]</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">m2</span>
<span class="n">r</span> <span class="o">=</span> <span class="o">-></span> <span class="p">{</span>
<span class="nb">proc</span> <span class="o">=</span> <span class="no">Proc</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="k">return</span> <span class="ss">:return</span> <span class="p">}</span>
<span class="p">}.</span><span class="nf">call</span>
<span class="n">r</span><span class="p">.</span><span class="nf">call</span> <span class="c1">#return from method</span>
<span class="ss">:never_reached</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="n">m1</span> <span class="c1">#=> [:after_in_method, :return]</span>
<span class="nb">p</span> <span class="n">m2</span> <span class="c1">#=> :return</span>
</code></pre> Ruby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=869622020-08-06T23:47:18ZEregon (Benoit Daloze)
<ul></ul><p>IMHO it should be a LocalJumpError. The Proc should return to the lambda, that's syntactically the closest scope it should return to.<br>
Since it's not possible to return to it (the lambda is no longer on stack), it should be a LocalJumpError.</p> Ruby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=869842020-08-09T10:41:20Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul></ul><p>+1 to <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/772">@Eregon (Benoit Daloze)</a> ’s interpretation. Current behaviour is at least very cryptic.</p> Ruby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=870422020-08-12T21:29:09Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>Just to be clear I am +1 on single return target, as described here: <a href="https://github.com/jruby/jruby/issues/6350#issuecomment-669603740" class="external">https://github.com/jruby/jruby/issues/6350#issuecomment-669603740</a></p>
<p>In addition to the confusing (and possibly inefficient) behavior that results from having two possible return targets, there's also a bug potential here if someone "accidentally" allows a proc containing a return to escape from its lambda container. Rather than returning from the lambda as it should have done, it will now return from the next "returnable" scope, and likely interrupt execution in an unexpected way.</p>
<p>I would challenge anyone to explain why the current behavior <em>should</em> exist, since I can't think of a single valid use case. If there's no use case for a confusing "feature", we should remove it.</p> Ruby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=873112020-08-31T09:00:33Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><p>It is intentional since 1.6.0. But I am OK with making <code>m2</code> raise <code>LocalJumpError</code>.<br>
Ask <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/17">@ko1 (Koichi Sasada)</a> about migration.</p>
<p>Matz.</p> Ruby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=905832021-02-25T02:22:34Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>I added a pull request to fix this: <a href="https://github.com/ruby/ruby/pull/4223" class="external">https://github.com/ruby/ruby/pull/4223</a></p> Ruby master - Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a methodhttps://bugs.ruby-lang.org/issues/17105?journal_id=912342021-04-02T00:25:48Zko1 (Koichi Sasada)
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul><p>Applied in changeset <a class="changeset" title="fix return from orphan Proc in lambda A "return" statement in a Proc in a lambda like: `lambda..." href="https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/ecfa8dcdbaf60cbe878389439de9ac94bc82e034">git|ecfa8dcdbaf60cbe878389439de9ac94bc82e034</a>.</p>
<hr>
<p>fix return from orphan Proc in lambda</p>
<p>A "return" statement in a Proc in a lambda like:<br>
<code>lambda{ proc{ return }.call }</code><br>
should return outer lambda block. However, the inner Proc can become<br>
orphan Proc from the lambda block. This "return" escape outer-scope<br>
like method, but this behavior was decieded as a bug.<br>
[Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: A single `return` can return to two different places in a proc inside a lambda inside a method (Closed)" href="https://bugs.ruby-lang.org/issues/17105">#17105</a>]</p>
<p>This patch raises LocalJumpError by checking the proc is orphan or<br>
not from lambda blocks before escaping by "return".</p>
<p>Most of tests are written by Jeremy Evans<br>
<a href="https://github.com/ruby/ruby/pull/4223" class="external">https://github.com/ruby/ruby/pull/4223</a></p>