https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112021-10-21T16:17:39ZRuby Issue Tracking SystemRuby master - Bug #14083: Refinement in block calling incorrect methodhttps://bugs.ruby-lang.org/issues/14083?journal_id=942412021-10-21T16:17:39Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul><li><strong>Related to</strong> <i><a class="issue tracker-1 status-6 priority-4 priority-default closed" href="/issues/11704">Bug #11704</a>: Refinements only get "used" once in loop</i> added</li></ul> Ruby master - Bug #14083: Refinement in block calling incorrect methodhttps://bugs.ruby-lang.org/issues/14083?journal_id=1016402023-02-03T19:42:40Zalanwu (Alan Wu)
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Rejected</i></li></ul><p>This is working as intended. Scoping rules for refinements is similar<br>
to the scoping rules for constant resolution. The scope only<br>
changes when one uses the <code>class</code>/<code>module</code> keyword. In the posted<br>
example the two <code>using</code> calls act on the same scope; the refinement<br>
scope does not end when the block scope ends.</p>
<p>See also: <a href="https://bugs.ruby-lang.org/issues/11779#note-31" class="external">https://bugs.ruby-lang.org/issues/11779#note-31</a></p> Ruby master - Bug #14083: Refinement in block calling incorrect methodhttps://bugs.ruby-lang.org/issues/14083?journal_id=1020892023-03-01T11:09:43ZEregon (Benoit Daloze)
<ul></ul><p>My reading of <a href="https://bugs.ruby-lang.org/projects/ruby-master/wiki/RefinementsSpec#Scope-of-refinements" class="external">https://bugs.ruby-lang.org/projects/ruby-master/wiki/RefinementsSpec#Scope-of-refinements</a> is that the expected output here is:</p>
<blockquote>
<p>A refinement is activated in a certain scope.The scope of a refinement is lexical in the sense that, when control is transferred outside the scope (e.g., by an invocation of a method defined outside the scope, by load/require, etc...), the refinement is deactivated.In the body of a method defined in a scope where a refinement is activated, the refinement is activated even if the method is invoked outside the scope.</p>
</blockquote>
<p>Given the scope is limited by <code>class</code>/<code>module</code> keywords like constant scopes (<a href="https://bugs.ruby-lang.org/issues/11779#note-31" class="external">https://bugs.ruby-lang.org/issues/11779#note-31</a>), it should be:</p>
<pre><code>Example#test
Example#test in M1
Example#test
Example#test in M1
</code></pre>
<p>which is what TruffleRuby does currently.<br>
Seeing both M1 and M2 from the same call site wouldn't be lexical.</p>
<p>The reason we don't see M2 there is changing the refinements for a scope after there have been calls is AFAIK an incorrect usages of refinements (ideally <code>using</code> would raise for such a case, but it might be difficult to detect).<br>
In other words, refinements at a given call site must always be the same and so it's enough to consider refinements during the initial lookup for the cache and not after.<br>
This is the key point after the very long discussion on the mailing list about the original design of refinements (at least that's what I recall from it), they must not have dynamic rebinding so they don't have extra cost (e.g. on non-refined method calls when in a scope with some refinements activated, and also obviously nobody wants to check if there are active refinements at every call site), the refinements for a given call site should be fixed and never change. If they change, it's an incorrect usage and it should be fair to just ignore the change (what TruffleRuby does, or even better to raise an error in that case).</p>
<p>In practice, I believe real usages of <code>using</code> are only early at the top-level, much like <code>require</code>, and maybe sometimes at the beginning of a <code>module</code>/<code>class</code> body.<br>
Both of these are fine and can't run into this problem (well, except if they meant to <code>refine</code> <code>require</code> but then it's only natural to call <code>using</code> before <code>require</code>).</p>
<p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/12">@shugo (Shugo Maeda)</a> What do you think about this?<br>
I think we should try to raise an error for <code>using</code> in such invalid cases.<br>
That would make it much easier to fix <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Performance regression when invoking refined methods (Closed)" href="https://bugs.ruby-lang.org/issues/18572">#18572</a> on CRuby and allow simplifying the implementation of refinements on CRuby (e.g., TruffleRuby doesn't track if a method has refinements).</p> Ruby master - Bug #14083: Refinement in block calling incorrect methodhttps://bugs.ruby-lang.org/issues/14083?journal_id=1020902023-03-01T11:10:00ZEregon (Benoit Daloze)
<ul><li><strong>Related to</strong> <i><a class="issue tracker-1 status-5 priority-4 priority-default closed" href="/issues/18572">Bug #18572</a>: Performance regression when invoking refined methods</i> added</li></ul>