From: Damien.Olivier.Robert+ruby@... Date: 2017-03-15T08:30:47+00:00 Subject: [ruby-core:80174] [Ruby trunk Bug#13271] Clarifications on refinement spec Issue #13271 has been updated by Gondolin (Damien Robert). Thanks for the answers! shugo (Shugo Maeda) wrote: > The behavior of my first proposal was what you expected, but it was changed to reduce implicit effects of refinements. So should I expect that in future ruby versions `using M` will not also activate the refinements of included and prepended modules of `M`? > This behavior seems strange, and may be a bug of the implementation. Ok! > refinement:Foo@M1 is not active in the definitions of Bar#foo and Bar#bar, so super in them > never invoke refinement:Foo@M1#foo. Oh of course, the definition of Bar#foo is in a lexical scope where the refinements were not active, so since refinements work with the lexical scope they won't be activated there, thanks! ---------------------------------------- Bug #13271: Clarifications on refinement spec https://bugs.ruby-lang.org/issues/13271#change-63615 * Author: Gondolin (Damien Robert) * Status: Assigned * Priority: Normal * Assignee: shugo (Shugo Maeda) * Target version: * ruby -v: ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux] * Backport: 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN ---------------------------------------- Consider the following code: ~~~ruby class Foo def foo "Foo#foo" end def bar "Foo#bar" end end class Bar < Foo def foo "Bar#foo -> "+super end def bar "Bar#bar -> "+super end end module R1 def foo "R1#foo -> "+super end def bar "R1#bar -> "+super end end module R2 def foo "R2#foo -> "+super end def bar "R2#bar -> "+super end end module M2 refine Foo do include R2 def foo "refinement:Foo@M2#foo -> "+super end def bar "refinement:Foo@M2#bar -> "+super end end end module M1 include M2 refine Foo do include R1 def foo "refinement:Foo@M1#foo -> "+super end end end using M1 puts Foo.new.foo #refinement:Foo@M1#foo -> R1#foo -> Foo#foo puts Foo.new.bar #R1#bar -> refinement:Foo@M2#bar -> R2#bar -> Foo#bar puts Bar.new.foo #Bar#foo -> Foo#foo puts Bar.new.bar #Bar#bar -> Foo#bar ~~~ I have several questions about the results. 1) As I was expecting, '`using M1`' not only activate the refinements of `M1` but also the refinements of the included module `M2`. In other word it behaves as if I had specified '`using M2; using M1`'. This is what I was expecting but from reading the spec "(3) Activate refinements in the defined refinement table of `mod`" it looks like the spec only speak about the refined modules in `M1`. 2) As noted in the spec, `refinement:Foo@M1` should behave as if its superclass was `Foo`, so the fact that `Foo.new.foo` does not go through the refinements of `M2` was expected. However I find the result of '`Foo.new.bar`' strange: `refinement:Foo@M1` does not contain the bar method, but its included module `R1` does. So should not the result be `R1#bar -> Foo#bar`, whithout going through the refinements methods of `M2`? The spec states "(3) If `C` has included modules, for these modules `M` If a method with name `N` found in the method table of `M`, return the method." But it does not stipulate what happen if we call super in one of these included method. 3) I am also surprised by the behaviour of `Bar.new.foo` and `Bar.new.bar`. According to the spec: "(7) If `C` has a direct superclass, search the method `N` as specified in "Normal method lookup" from Step 4, where `C` is the superclass." and Step 4 start by looking at the activated refinements. So I was expecting the results to go through `Foo`'s refinement, so that for instance '`Bar.new.foo`' would be `Bar#foo -> refinement:Foo@M1#foo -> R1#foo -> Foo#foo` -- https://bugs.ruby-lang.org/ Unsubscribe: