Project

General

Profile

Actions

Bug #13271

closed

Clarifications on refinement spec

Added by Gondolin (Damien Robert) over 7 years ago. Updated almost 7 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux]
[ruby-core:79880]

Description

Consider the following code:

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

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0