Issue #11120 has been updated by Pierre Schambacher.


Actually I really think that solution 1 is the good one. Here is another code sample:

~~~
module A
  def run
    puts 'RUN STARTS'
    super
    puts 'RUN ENDS'
  end

  def run_without_chain
    puts 'RUN_WITHOUT_CHAIN STARTS'
    super
    puts 'RUN_WITHOUT_CHAIN ENDS'
  end
end

class B
  def run
    puts 'B STARTS'
    puts 'B ENDS'
  end
  prepend A
  alias_method :run_without_chain, :run
end

B.new.run_without_chain
~~~

Here I would expect this output:

~~~
RUN_WITHOUT_CHAIN STARTS
B STARTS
B ENDS
RUN_WITHOUT_CHAIN ENDS
~~~

But this is the one I get:

~~~
RUN_WITHOUT_CHAIN STARTS
RUN STARTS
B STARTS
B ENDS
RUN ENDS
RUN_WITHOUT_CHAIN ENDS
~~~

To obtain the result I would like to get, I have to put the alias_method **before** the prepend. That doesn't feel really right for me since aliasing a method and prepending a module in the ancestors are pretty independent actions and they should not be order dependent.

----------------------------------------
Bug #11120: Unexpected behavior when mixing Module#prepend with method aliasing
https://bugs.ruby-lang.org/issues/11120#change-56247

* Author: Pablo Herrero
* Status: Open
* Priority: Normal
* Assignee: 
* ruby -v: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
----------------------------------------
I'm not completely sure myself if this should be considered a bug, but at least it should be up for discussion.

I stumbled upon this behavior when migrating some code using alias chains to Module#prepend.
Consider the following code:

```ruby
# thingy.rb
class Thingy
  def thingy
    puts "thingy"
  end
end

# thingy_with_foo.rb
module ThingyWithFoo
  def thingy
    puts "thingy with foo"
    super
  end
end

Thingy.prepend(ThingyWithFoo)

# thingy_with_bar.rb
class Thingy
  alias_method :thingy_without_bar, :thingy # Wont't alias create an alias for Thingy#thingy but ThingyWithFoo#thingy instead

  def thingy_with_bar
    puts "thingy with bar"
    thingy_without_bar # Expected to call original Thingy#thingy method but will call prepended method instead
  end

  alias_method :thingy, :thingy_with_bar
end

# some_file.rb
Thingy.new.thingy # raises: stack level too deep (SystemStackError))
```

In a nutshell when calling `super` from `ThingyWithFoo#foo` it will call `thingy_with_bar` method, and this method will call back to `ThingyWithFoo#foo` by invoking `thingy_without_bar`, thus producing an endless loop.

This situation arises because `alias_method` is producing an alias not for the Thingy#thingy method the but for the upper method from `ThingyWithFoo` instead. May be this behavior could be considered correct, I'm still not sure, but it will probably became a problem for source code migrating from alias chains to use `Modue#prepend`, specially when other active gems could potentially still be using alias chains themselves without the user knowledge.



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>