Feature #1586 [ruby-core:23740]

Including a module already present in ancestors should not be ignored

Added by Jeremy Kemper 247 days ago. Updated 247 days ago.

Status :Open Start :06/07/2009
Priority :Normal Due date :
Assigned to :Yukihiro Matsumoto % Done :

0%

Category :core
Target version :2.0

Description

The scenario:
* I include Foo in Numeric to provide #bar
* Some other library includes a module in Float to provide #bar
* So I include Foo in Float to use my #bar
* But including Foo in Float is ignored since it's already in the ancestor chain

I think it should be added to the ancestor chain, even if it's already present, since I may want to override some other method earlier in the ancestor chain.

# Including a module already included in a superclass is ignored
>> module Foo; end
=> nil
>> class Numeric; include Foo; end
=> Numeric
>> Float.ancestors
=> [Float, Precision, Numeric, Foo, Comparable, Object, Kernel]
>> class Float; include Foo; end
=> Float
>> Float.ancestors
=> [Float, Precision, Numeric, Foo, Comparable, Object, Kernel]
 
# Reversing the order of inclusion works as expected
>> module Foo; end
=> nil
>> class Float; include Foo; end
=> Float
>> Float.ancestors
=> [Float, Foo, Precision, Numeric, Comparable, Object, Kernel]
>> class Numeric; include Foo; end
=> Numeric
>> Float.ancestors
=> [Float, Foo, Precision, Numeric, Foo, Comparable, Object, Kernel]
 
# And so does including a dupe of the existing module in the subclass
>> module Foo; end
=> nil
>> class Numeric; include Foo; end
=> Numeric
>> Float.ancestors
=> [Float, Precision, Numeric, Foo, Comparable, Object, Kernel]
>> class Float; include Foo.dup; end
=> Float
>> Float.ancestors
=> [Float, #<Module:0x19bcd40>, Precision, Numeric, Foo, Comparable, Object, Kernel]

History

06/07/2009 10:22 AM - Nobuyoshi Nakada

  • Category set to core
  • Assigned to set to Yukihiro Matsumoto
  • Target version set to 2.0

06/07/2009 10:48 AM - Rick DeNatale

Actually, for a while, back in 2006, Ruby 1.9 (in its experimental form) used to do just what this ticket asks for:

http://talklikeaduck.denhaven2.com/2006/10/09/a-subtle-change-to-mixin-semantics-in-ruby-1-9

However, that change got reverted.

I asked Matz why at RubyConf 2007, and documented our conversion

http://talklikeaduck.denhaven2.com/2007/11/03/a-chat-with-matz-classs-variable-reversion-and-a-mystery-explained

The problem is that MRI, and I guess YARV doesn't keep track of where in the chain of classes, and module proxies it found the currently executing method, so super is implemented by doing a method search starting with the klass of self, and proceding until the method is found a SECOND time.  With this implementation it's easier to turn module re-inclusion into a nop than to deal with the consequences.

06/07/2009 12:30 PM - Jeremy Kemper

Fascinating. Thanks for the history behind this, Rick.

Despite the implementation difficulties, I'd like to see this choice revisited for a future Ruby. I consider it a bug.

Also available in: Atom PDF