Project

General

Profile

Bug #11120

Unexpected behavior when mixing Module#prepend with method aliasing

Added by pabloh (Pablo Herrero) about 5 years ago. Updated 12 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
[ruby-core:69073]

Description

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 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.

Also available in: Atom PDF