Unexpected behavior when mixing Module#prepend with method aliasing
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:
# 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
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.