https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112011-03-26T22:25:29ZRuby Issue Tracking SystemRuby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=162062011-03-26T22:25:29Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li></ul> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=177462011-06-11T15:49:30Zko1 (Koichi Sasada)
<ul></ul><p>まつもとさん,こちらいかがでしょうか.<br>
直せと言われたら私なのかなぁ.</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=177522011-06-11T16:04:34Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p><a href="http://redmine.ruby-lang.org/issues/4440" class="external">http://redmine.ruby-lang.org/issues/4440</a><br>
に matz の返事があります。</p>
<blockquote>
<p>優先順位は高くありませんが、直すべきだと思います。</p>
<p>とはいうものの、1.8のころからこうだったのですし、直すのが難しいのも確<br>
かなのですが。</p>
</blockquote>
<p>確か redmine の更新直後で、インターフェイスの違いにハマってチケット登録に失敗してしまったのでした。</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=178072011-06-11T22:29:10Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul><li><strong>ruby -v</strong> changed from <i>ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]</i> to <i>-</i></li></ul><p>まつもと ゆきひろです</p>
<p>In message "Re: <a href="https://blade.ruby-lang.org/ruby-dev/43724">[ruby-dev:43724]</a> [Ruby 1.9 - Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: odd evaluation order in a multiple assignment (Closed)" href="https://bugs.ruby-lang.org/issues/4443">#4443</a>] odd evaluation order in a multiple assignment"<br>
on Sat, 11 Jun 2011 15:49:30 +0900, Koichi Sasada <a href="mailto:redmine@ruby-lang.org" class="email">redmine@ruby-lang.org</a> writes:</p>
<blockquote>
<p>まつもとさん,こちらいかがでしょうか.<br>
直せと言われたら私なのかなぁ.</p>
</blockquote>
<p>すでに遠藤さんが指摘してくださいましたが、直せるものなら直し<br>
たいと思ってます。</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=178082011-06-11T22:29:10Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><p>まつもと ゆきひろです</p>
<p>In message "Re: <a href="https://blade.ruby-lang.org/ruby-dev/43724">[ruby-dev:43724]</a> [Ruby 1.9 - Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: odd evaluation order in a multiple assignment (Closed)" href="https://bugs.ruby-lang.org/issues/4443">#4443</a>] odd evaluation order in a multiple assignment"<br>
on Sat, 11 Jun 2011 15:49:30 +0900, Koichi Sasada <a href="mailto:redmine@ruby-lang.org" class="email">redmine@ruby-lang.org</a> writes:</p>
<p>|まつもとさん,こちらいかがでしょうか.<br>
|直せと言われたら私なのかなぁ.</p>
<p>すでに遠藤さんが指摘してくださいましたが、直せるものなら直し<br>
たいと思ってます。</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=213732011-10-18T09:16:39Znaruse (Yui NARUSE)naruse@airemix.jp
<ul><li><strong>Project</strong> changed from <i>Ruby master</i> to <i>14</i></li><li><strong>Target version</strong> deleted (<del><i>3.0</i></del>)</li></ul> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=214822011-10-23T17:21:09Znaruse (Yui NARUSE)naruse@airemix.jp
<ul><li><strong>Project</strong> changed from <i>14</i> to <i>Ruby master</i></li></ul> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=257942012-04-10T18:35:13Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><p>Cから受け継いだ代入の評価順が「おかしい」のが原因である(本来は a → b と表記すべきか)ことを考えると、<br>
むしろ foo[0] = bar が :bar, :fooと動作するようにすべきでしょうか。</p>
<p>いや、単なる思いつきなのですが。</p>
<p>ちなみに今調べたら mruby は foo[0] = bar が :bar, :fooと動作しますね。</p>
<p>Matz.</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=258022012-04-10T20:57:08Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>まあ、それはそれでいいかなと思います。<br>
ちなみに ISO とかの標準的にはどうなってるんでしょう?</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=262442012-04-27T14:28:08Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><p>手元にあるJIS x3017のドラフトを見ると現状の評価順(多重代入の場合には右辺が先)が記述してありますね(11.4.2.4)。<br>
どうしたもんだか。</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=280322012-07-14T14:51:16Zko1 (Koichi Sasada)
<ul><li><strong>Assignee</strong> changed from <i>matz (Yukihiro Matsumoto)</i> to <i>ko1 (Koichi Sasada)</i></li></ul> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=280332012-07-14T14:56:10Zko1 (Koichi Sasada)
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li></ul><p>duplicated (<a href="http://bugs.ruby-lang.org/issues/4443" class="external">http://bugs.ruby-lang.org/issues/4443</a>)</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=315842012-10-26T05:33:56Znahi (Hiroshi Nakamura)nakahiro@gmail.com
<ul><li><strong>Status</strong> changed from <i>Closed</i> to <i>Open</i></li></ul><p>It looks to be closed by mistake.</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=319532012-10-30T09:08:54Zko1 (Koichi Sasada)
<ul><li><strong>Category</strong> set to <i>core</i></li><li><strong>Target version</strong> set to <i>2.6</i></li></ul><p>...これバグなんだっけ? feature のような気もしますが.<br>
2.0 には無理っぽいので,next minor にしておきます.</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=539372015-08-21T21:09:39Zko1 (Koichi Sasada)
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/53937/diff?detail_id=38766">diff</a>)</li></ul> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=627672017-01-31T09:01:34Zko1 (Koichi Sasada)
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/62767/diff?detail_id=43816">diff</a>)</li></ul><p>今更ですが、考えます(いつだろう...)。</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=645352017-04-28T13:45:41Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li></ul> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=697482018-01-24T08:36:44Zakr (Akira Tanaka)akr@fsij.org
<ul></ul><p>関連すると思われるささださんの昔のメールを見つけました: ruby-dev:31579</p>
<pre><code>1) 右辺が重複しないローカル変数の列だったら今まで通り
(副作用はないので問題ない)
2) そうじゃなければ,色々コストをかけて順番通りに実行
ということにしたいと思います.多分,(1) がほとんどではないかと期待.
ネストした多重代入は (1) にはあてはまりませんが,まぁしょうがない.
</code></pre> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=916142021-04-20T00:11:32Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>I have submitted a pull request to fix multiple assignment evaluation order: <a href="https://github.com/ruby/ruby/pull/4390" class="external">https://github.com/ruby/ruby/pull/4390</a></p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=916442021-04-21T17:49:41Zjeremyevans (Jeremy Evans)code@jeremyevans.net
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li></ul><p>Applied in changeset <a class="changeset" title="Evaluate multiple assignment left hand side before right hand side In regular assignment, Ruby e..." href="https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/50c54d40a81bb2a4794a6be5f1861152900b4fed">git|50c54d40a81bb2a4794a6be5f1861152900b4fed</a>.</p>
<hr>
<p>Evaluate multiple assignment left hand side before right hand side</p>
<p>In regular assignment, Ruby evaluates the left hand side before<br>
the right hand side. For example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">foo</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">bar</span>
</code></pre>
<p>Calls <code>foo</code>, then <code>bar</code>, then <code>[]=</code> on the result of <code>foo</code>.</p>
<p>Previously, multiple assignment didn't work this way. If you did:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">abc</span><span class="p">.</span><span class="nf">def</span><span class="p">,</span> <span class="n">foo</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">bar</span><span class="p">,</span> <span class="n">baz</span>
</code></pre>
<p>Ruby would previously call <code>bar</code>, then <code>baz</code>, then <code>abc</code>, then<br>
<code>def=</code> on the result of <code>abc</code>, then <code>foo</code>, then <code>[]=</code> on the<br>
result of <code>foo</code>.</p>
<p>This change makes multiple assignment similar to single assignment,<br>
changing the evaluation order of the above multiple assignment code<br>
to calling <code>abc</code>, then <code>foo</code>, then <code>bar</code>, then <code>baz</code>, then <code>def=</code> on<br>
the result of <code>abc</code>, then <code>[]=</code> on the result of <code>foo</code>.</p>
<p>Implementing this is challenging with the stack-based virtual machine.<br>
We need to keep track of all of the left hand side attribute setter<br>
receivers and setter arguments, and then keep track of the stack level<br>
while handling the assignment processing, so we can issue the<br>
appropriate topn instructions to get the receiver. Here's an example<br>
of how the multiple assignment is executed, showing the stack and<br>
instructions:</p>
<pre><code>self # putself
abc # send
abc, self # putself
abc, foo # send
abc, foo, 0 # putobject 0
abc, foo, 0, [bar, baz] # evaluate RHS
abc, foo, 0, [bar, baz], baz, bar # expandarray
abc, foo, 0, [bar, baz], baz, bar, abc # topn 5
abc, foo, 0, [bar, baz], baz, abc, bar # swap
abc, foo, 0, [bar, baz], baz, def= # send
abc, foo, 0, [bar, baz], baz # pop
abc, foo, 0, [bar, baz], baz, foo # topn 3
abc, foo, 0, [bar, baz], baz, foo, 0 # topn 3
abc, foo, 0, [bar, baz], baz, foo, 0, baz # topn 2
abc, foo, 0, [bar, baz], baz, []= # send
abc, foo, 0, [bar, baz], baz # pop
abc, foo, 0, [bar, baz] # pop
[bar, baz], foo, 0, [bar, baz] # setn 3
[bar, baz], foo, 0 # pop
[bar, baz], foo # pop
[bar, baz] # pop
</code></pre>
<p>As multiple assignment must deal with splats, post args, and any level<br>
of nesting, it gets quite a bit more complex than this in non-trivial<br>
cases. To handle this, struct masgn_state is added to keep<br>
track of the overall state of the mass assignment, which stores a linked<br>
list of struct masgn_attrasgn, one for each assigned attribute.</p>
<p>This adds a new optimization that replaces a topn 1/pop instruction<br>
combination with a single swap instruction for multiple assignment<br>
to non-aref attributes.</p>
<p>This new approach isn't compatible with one of the optimizations<br>
previously used, in the case where the multiple assignment return value<br>
was not needed, there was no lhs splat, and one of the left hand side<br>
used an attribute setter. This removes that optimization. Removing<br>
the optimization allowed for removing the POP_ELEMENT and adjust_stack<br>
functions.</p>
<p>This adds a benchmark to measure how much slower multiple<br>
assignment is with the correct evaluation order.</p>
<p>This benchmark shows:</p>
<ul>
<li>4-9% decrease for attribute sets</li>
<li>14-23% decrease for array member sets</li>
<li>Basically same speed for local variable sets</li>
</ul>
<p>Importantly, it shows no significant difference between the popped<br>
(where return value of the multiple assignment is not needed) and<br>
!popped (where return value of the multiple assignment is needed)<br>
cases for attribute and array member sets. This indicates the<br>
previous optimization, which was dropped in the evaluation<br>
order fix and only affected the popped case, is not important to<br>
performance.</p>
<p>Fixes [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: odd evaluation order in a multiple assignment (Closed)" href="https://bugs.ruby-lang.org/issues/4443">#4443</a>]</p> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=918442021-05-05T15:24:46ZEregon (Benoit Daloze)
<ul><li><strong>Related to</strong> <i><a class="issue tracker-1 status-5 priority-4 priority-default closed" href="/issues/15928">Bug #15928</a>: Constant declaration does not conform to JIS 3017:2013</i> added</li></ul> Ruby master - Bug #4443: odd evaluation order in a multiple assignmenthttps://bugs.ruby-lang.org/issues/4443?journal_id=918472021-05-05T15:46:21ZEregon (Benoit Daloze)
<ul></ul><p>I wrote some concerns over this change in <a href="https://bugs.ruby-lang.org/issues/15928#note-10" class="external">https://bugs.ruby-lang.org/issues/15928#note-10</a>.<br>
I think the previous semantics of multiple assignments are better for various reasons.<br>
We could change single assignment order, always evaluate RHS first, like MRuby behaves, if consistency is wanted.</p>