https://bugs.ruby-lang.org/
https://bugs.ruby-lang.org/favicon.ico?1711330511
2021-01-08T19:29:20Z
Ruby Issue Tracking System
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=89833
2021-01-08T19:29:20Z
fledman (David Feldman)
<ul></ul><p>since :except is only available natively on Ruby3, here is a Ruby2 demonstration:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">irb</span><span class="o">></span> <span class="no">RUBY_VERSION</span>
<span class="o">=></span> <span class="s2">"2.7.2"</span>
<span class="n">irb</span><span class="o">></span> <span class="k">module</span> <span class="nn">Nothing</span><span class="p">;</span> <span class="k">end</span><span class="p">;</span> <span class="no">Hash</span><span class="p">.</span><span class="nf">prepend</span><span class="p">(</span><span class="no">Nothing</span><span class="p">);</span> <span class="no">Hash</span><span class="p">.</span><span class="nf">ancestors</span>
<span class="o">=></span> <span class="p">[</span><span class="no">Nothing</span><span class="p">,</span> <span class="no">Hash</span><span class="p">,</span> <span class="no">Enumerable</span><span class="p">,</span> <span class="no">Object</span><span class="p">,</span> <span class="no">PP</span><span class="o">::</span><span class="no">ObjectMixin</span><span class="p">,</span> <span class="no">Kernel</span><span class="p">,</span> <span class="no">BasicObject</span><span class="p">]</span>
<span class="n">irb</span><span class="o">></span> <span class="k">module</span> <span class="nn">NeverUsed</span>
<span class="n">refine</span> <span class="no">Hash</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">fetch</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="mi">42</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="o">=></span> <span class="c1">#<refinement:Hash@NeverUsed></span>
<span class="n">irb</span><span class="o">></span> <span class="n">test_visibility</span> <span class="ss">:fetch</span>
<span class="no">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="mi">6</span><span class="p">:</span> <span class="n">from</span> <span class="sr">/Users/</span><span class="n">davidfeldman</span><span class="o">/</span><span class="p">.</span><span class="nf">rubies</span><span class="o">/</span><span class="n">ruby</span><span class="o">-</span><span class="mf">2.7</span><span class="o">.</span><span class="mi">2</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">irb</span><span class="p">:</span><span class="mi">23</span><span class="ss">:in</span> <span class="sb">`<main>'
5: from /Users/davidfeldman/.rubies/ruby-2.7.2/bin/irb:23:in `</span><span class="nb">load</span><span class="s1">'
4: from /Users/davidfeldman/.rubies/ruby-2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'</span>
<span class="mi">3</span><span class="p">:</span> <span class="n">from</span> <span class="p">(</span><span class="n">irb</span><span class="p">):</span><span class="mi">25</span>
<span class="mi">2</span><span class="p">:</span> <span class="n">from</span> <span class="p">(</span><span class="n">irb</span><span class="p">):</span><span class="mi">14</span><span class="ss">:in</span> <span class="sb">`test_visibility'
1: from (irb):14:in `</span><span class="kp">private</span><span class="s1">'
NameError (undefined method `fetch` for class `#<Class:#<Hash:0x00007fcdf3ac7ec0>>'</span><span class="p">)</span>
<span class="c1"># non-refined method still works</span>
<span class="n">irb</span><span class="o">></span> <span class="n">test_visibility</span> <span class="ss">:[]</span>
<span class="n">hit</span> <span class="no">NoMethodError</span> <span class="n">as</span> <span class="ss">expected: </span><span class="c1">#<NoMethodError: private method `[]` called for {:x=>1, :y=>1}:Hash Did you mean? []=></span>
<span class="mi">2</span>
<span class="o">=></span> <span class="kp">nil</span>
</code></pre>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=89834
2021-01-08T19:45:58Z
fledman (David Feldman)
<ul></ul><p>and a demonstration with a custom class:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">RUBY_VERSION</span>
<span class="k">class</span> <span class="nc">Thing</span>
<span class="k">def</span> <span class="nf">direction</span>
<span class="s1">'LEFT'</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">test_thing_visibility</span>
<span class="n">t1</span> <span class="o">=</span> <span class="no">Thing</span><span class="p">.</span><span class="nf">new</span>
<span class="n">t2</span> <span class="o">=</span> <span class="no">Thing</span><span class="p">.</span><span class="nf">new</span>
<span class="n">t1</span><span class="p">.</span><span class="nf">singleton_class</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:private</span><span class="p">,</span> <span class="ss">:direction</span><span class="p">)</span>
<span class="n">t2</span><span class="p">.</span><span class="nf">singleton_class</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:public</span><span class="p">,</span> <span class="ss">:direction</span><span class="p">)</span>
<span class="k">begin</span>
<span class="nb">puts</span> <span class="n">t1</span><span class="p">.</span><span class="nf">direction</span>
<span class="k">rescue</span> <span class="no">NoMethodError</span> <span class="o">=></span> <span class="n">err</span>
<span class="nb">puts</span> <span class="s2">"hit NoMethodError as expected: </span><span class="si">#{</span><span class="n">err</span><span class="p">.</span><span class="nf">inspect</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="nb">puts</span> <span class="n">t2</span><span class="p">.</span><span class="nf">direction</span>
<span class="k">end</span>
<span class="n">test_thing_visibility</span>
<span class="k">module</span> <span class="nn">NeverUsed</span>
<span class="n">refine</span> <span class="no">Thing</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">direction</span>
<span class="s1">'UP'</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">test_thing_visibility</span>
<span class="k">module</span> <span class="nn">Nothing</span><span class="p">;</span> <span class="k">end</span><span class="p">;</span> <span class="no">Thing</span><span class="p">.</span><span class="nf">prepend</span><span class="p">(</span><span class="no">Nothing</span><span class="p">);</span> <span class="no">Thing</span><span class="p">.</span><span class="nf">ancestors</span>
<span class="n">test_thing_visibility</span>
</code></pre>
<p>outputs:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">=></span> <span class="s2">"2.6.6"</span>
<span class="o">=></span> <span class="ss">:direction</span>
<span class="o">=></span> <span class="ss">:test_thing_visibility</span>
<span class="n">hit</span> <span class="no">NoMethodError</span> <span class="n">as</span> <span class="ss">expected: </span><span class="c1">#<NoMethodError: private method `direction' called for #<Thing:0x00007f8c6f871ce0>></span>
<span class="no">LEFT</span>
<span class="o">=></span> <span class="kp">nil</span>
<span class="o">=></span> <span class="c1">#<refinement:Thing@NeverUsed></span>
<span class="n">hit</span> <span class="no">NoMethodError</span> <span class="n">as</span> <span class="ss">expected: </span><span class="c1">#<NoMethodError: private method `direction' called for #<Thing:0x00007f8c6f8b4a68>></span>
<span class="no">LEFT</span>
<span class="o">=></span> <span class="kp">nil</span>
<span class="o">=></span> <span class="p">[</span><span class="no">Nothing</span><span class="p">,</span> <span class="no">Thing</span><span class="p">,</span> <span class="no">Object</span><span class="p">,</span> <span class="no">PP</span><span class="o">::</span><span class="no">ObjectMixin</span><span class="p">,</span> <span class="no">Kernel</span><span class="p">,</span> <span class="no">BasicObject</span><span class="p">]</span>
<span class="no">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="mi">6</span><span class="p">:</span> <span class="n">from</span> <span class="sr">/Users/</span><span class="n">davidfeldman</span><span class="o">/</span><span class="p">.</span><span class="nf">rubies</span><span class="o">/</span><span class="n">ruby</span><span class="o">-</span><span class="mf">2.6</span><span class="o">.</span><span class="mi">6</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">irb</span><span class="p">:</span><span class="mi">23</span><span class="ss">:in</span> <span class="sb">`<main>'
5: from /Users/davidfeldman/.rubies/ruby-2.6.6/bin/irb:23:in `</span><span class="nb">load</span><span class="s1">'
4: from /Users/davidfeldman/.rubies/ruby-2.6.6/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'</span>
<span class="mi">3</span><span class="p">:</span> <span class="n">from</span> <span class="p">(</span><span class="n">irb</span><span class="p">):</span><span class="mi">37</span>
<span class="mi">2</span><span class="p">:</span> <span class="n">from</span> <span class="p">(</span><span class="n">irb</span><span class="p">):</span><span class="mi">11</span><span class="ss">:in</span> <span class="sb">`test_thing_visibility'
1: from (irb):11:in `</span><span class="kp">private</span><span class="s1">'
NameError (undefined method `direction'</span> <span class="k">for</span> <span class="k">class</span> <span class="sb">`#<Class:#<Thing:0x00007f8c6f8dcd10>>')
</span></code></pre>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=89850
2021-01-11T19:01:50Z
fledman (David Feldman)
<ul></ul><p>although the title makes it sound obscure, this bug is actually fairly easy to trigger when using rspec and rails:</p>
<ul>
<li>activesupport >= 5 prepends a module onto Hash</li>
<li>i18n >= 1.3 refines several methods on Hash</li>
<li>power_assert (used by test-unit and minitest) refines most of the basic operators of the core classes</li>
</ul>
<p>e.g. try to <a href="https://github.com/rspec/rspec-rails/issues/2394" class="external"><code>expect(some_hash).to receive(:except)</code></a></p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=90496
2021-02-19T00:00:20Z
jeremyevans0 (Jeremy Evans)
merch-redmine@jeremyevans.net
<ul></ul><p>I've added a pull request to fix this: <a href="https://github.com/ruby/ruby/pull/4200" class="external">https://github.com/ruby/ruby/pull/4200</a></p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=90948
2021-03-16T19:10:25Z
jeremyevans (Jeremy Evans)
code@jeremyevans.net
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul><p>Applied in changeset <a class="changeset" title="Skip refined method when exporting methods with changed visibility Previously, attempting to cha..." href="https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/58660e943488778563b9e41005a601e9660ce21f">git|58660e943488778563b9e41005a601e9660ce21f</a>.</p>
<hr>
<p>Skip refined method when exporting methods with changed visibility</p>
<p>Previously, attempting to change the visibility of a method in a<br>
singleton class for a class/module that is prepended to and refined<br>
would raise a NoMethodError.</p>
<p>Fixes [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: set_visibility fails when a prepended module and a refinement both exist (Closed)" href="https://bugs.ruby-lang.org/issues/17519">#17519</a>]</p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=90949
2021-03-16T19:12:51Z
fledman (David Feldman)
<ul></ul><p>do you plan to backport the fix to any of the supported 2.x versions?</p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=90950
2021-03-16T19:25:03Z
jeremyevans0 (Jeremy Evans)
merch-redmine@jeremyevans.net
<ul><li><strong>Backport</strong> changed from <i>2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN</i> to <i>2.5: UNKNOWN, 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED</i></li></ul><p>fledman (David Feldman) wrote in <a href="#note-6">#note-6</a>:</p>
<blockquote>
<p>do you plan to backport the fix to any of the supported 2.x versions?</p>
</blockquote>
<p>The choice of which patches to backport is up to the branch maintainer. I've marked this for backporting, but it is their decision.</p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=91020
2021-03-20T07:30:35Z
nagachika (Tomoyuki Chikanaga)
nagachika00@gmail.com
<ul><li><strong>Backport</strong> changed from <i>2.5: UNKNOWN, 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED</i> to <i>2.5: UNKNOWN, 2.6: REQUIRED, 2.7: DONE, 3.0: REQUIRED</i></li></ul><p>ruby_2_7 6e962f02b266c3a6c47e50cf2e9ab7b1db25e515 merged revision(s) 58660e943488778563b9e41005a601e9660ce21f.</p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=91242
2021-04-02T07:01:30Z
naruse (Yui NARUSE)
naruse@airemix.jp
<ul><li><strong>Backport</strong> changed from <i>2.5: UNKNOWN, 2.6: REQUIRED, 2.7: DONE, 3.0: REQUIRED</i> to <i>2.5: UNKNOWN, 2.6: REQUIRED, 2.7: DONE, 3.0: DONE</i></li></ul><p>ruby_3_0 d1cec0bca588266b9af1d55e592016c45ee68fbb merged revision(s) 58660e943488778563b9e41005a601e9660ce21f.</p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=91324
2021-04-05T21:52:06Z
fledman (David Feldman)
<ul></ul><p>this fix seems to have introduced a new but similar bug: <a href="https://github.com/ruby/ruby/pull/4200#issuecomment-813671308" class="external">https://github.com/ruby/ruby/pull/4200#issuecomment-813671308</a></p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=91325
2021-04-05T23:06:22Z
jeremyevans0 (Jeremy Evans)
merch-redmine@jeremyevans.net
<ul></ul><p>fledman (David Feldman) wrote in <a href="#note-10">#note-10</a>:</p>
<blockquote>
<p>this fix seems to have introduced a new but similar bug: <a href="https://github.com/ruby/ruby/pull/4200#issuecomment-813671308" class="external">https://github.com/ruby/ruby/pull/4200#issuecomment-813671308</a></p>
</blockquote>
<p>I can confirm the issue. Here's a pull request that fixes it: <a href="https://github.com/ruby/ruby/pull/4357" class="external">https://github.com/ruby/ruby/pull/4357</a></p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=91326
2021-04-05T23:14:01Z
jeremyevans0 (Jeremy Evans)
merch-redmine@jeremyevans.net
<ul><li><strong>Status</strong> changed from <i>Closed</i> to <i>Open</i></li></ul>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=91678
2021-04-23T23:31:50Z
jeremyevans (Jeremy Evans)
code@jeremyevans.net
<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 setting method visibility for a refinement without an origin class If a class has been refin..." href="https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/4b36a597f48c857aa5eb9ed80fec0d02f6284646">git|4b36a597f48c857aa5eb9ed80fec0d02f6284646</a>.</p>
<hr>
<p>Fix setting method visibility for a refinement without an origin class</p>
<p>If a class has been refined but does not have an origin class,<br>
there is a single method entry marked with VM_METHOD_TYPE_REFINED,<br>
but it contains the original method entry. If the original method<br>
entry is present, we shouldn't skip the method when searching even<br>
when skipping refined methods.</p>
<p>Fixes [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: set_visibility fails when a prepended module and a refinement both exist (Closed)" href="https://bugs.ruby-lang.org/issues/17519">#17519</a>]</p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=91682
2021-04-24T09:57:12Z
nagachika (Tomoyuki Chikanaga)
nagachika00@gmail.com
<ul><li><strong>Backport</strong> changed from <i>2.5: UNKNOWN, 2.6: REQUIRED, 2.7: DONE, 3.0: DONE</i> to <i>2.5: UNKNOWN, 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED</i></li></ul><p>reset Backport field to backport git|4b36a597f48c857aa5eb9ed80fec0d02f6284646.</p>
Ruby master - Bug #17519: set_visibility fails when a prepended module and a refinement both exist
https://bugs.ruby-lang.org/issues/17519?journal_id=92268
2021-05-29T05:56:43Z
nagachika (Tomoyuki Chikanaga)
nagachika00@gmail.com
<ul><li><strong>Backport</strong> changed from <i>2.5: UNKNOWN, 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED</i> to <i>2.5: UNKNOWN, 2.6: REQUIRED, 2.7: REQUIRED, 3.0: DONE</i></li></ul><p>ruby_3_0 7b6a2ad04a3272a31323493133498dfc60d77d76 merged revision(s) 4b36a597f48c857aa5eb9ed80fec0d02f6284646.</p>