Feature #1586

Including a module already present in ancestors should not be ignored

Added by Jeremy Kemper over 2 years ago. Updated 3 months ago.

[ruby-core:23740]
Status:Assigned Start date:06/07/2009
Priority:Normal Due date:
Assignee:Yukihiro Matsumoto % Done:

0%

Category:-
Target version:-

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

Updated by Nobuyoshi Nakada over 2 years ago

  • Category set to core
  • Assignee set to Yukihiro Matsumoto
  • Target version set to 3.0

Updated by Rick DeNatale over 2 years ago

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.

Updated by Jeremy Kemper over 2 years ago

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.

Updated by Shyouhei Urabe over 1 year ago

  • Status changed from Open to Assigned

Updated by Yui NARUSE 4 months ago

  • Project changed from ruby-trunk to 14
  • Category deleted (core)
  • Target version deleted (3.0)

Updated by Yui NARUSE 3 months ago

  • Project changed from 14 to ruby-trunk

Also available in: Atom PDF