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.
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.
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
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.
The behavior of my first proposal was what you expected, but it was changed to reduce implicit effects of refinements.
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.
This behavior seems strange, and may be a bug of the implementation.
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
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.
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!