VM searches for method relying on @superclass ivar, not on Module#direct_superclass. Is it a bug?

18 views
Skip to first unread message

Daniel Vartanov

unread,
Mar 26, 2011, 8:19:09 AM3/26/11
to rubinius-dev
Hi!

I tried to play with superclass chain and here is what I've
discovered:

The first example, @superclass is changed and method is being found
correctly:

https://gist.github.com/888224

# Step 1. Setting up environment

class Government
def power
"belongs to government"
end
end

module People
def power
"belogs to people"
end

Government.__send__ :include, self
end

government = Government.new


# Step 2. Swapping ancestors by re-setting @superclass

included_module = Government.instance_eval { @superclass }

government.metaclass.instance_eval { @superclass = included_module }
included_module.instance_eval { @superclass = Government }
Government.instance_eval { @superclass = Object }


# Step 3. Testing

puts government.metaclass.superclass_chain.inspect
# => [#<IncludedModule People>, Government, Object, #<IncludedModule
Kernel>] <-------- cool, prepended module is before Class
puts government.power
# => belongs to people <--------- this is definitely right


The second example. Module#direct_superclass is changed.
Module#superclass_chain gives correct result, but wrong method is
being called.

https://gist.github.com/888225

module Rubinius
class PrependedModule < IncludedModule
attr_reader :module

def initialize(mod, superclass)
@module = mod
@superclass = superclass
super(mod)
end

def inspect
"#<PrependedModule #{@module.to_s}>"
end
end
end

class Module
attr_reader :prepended_module # for the sake of simplicity let's
take just one for now

def prepend(mod)
@prepended_module = Rubinius::PrependedModule.new(mod, self)
end

def direct_superclass
if @superclass && @superclass.prepended_module &&
@superclass.prepended_module != self
@superclass.prepended_module
else
@superclass
end
end
end


# -----------------------------------------

class Government
def power
"belongs to government"
end
end

module People
def power
"belogs to people"
end

Government.prepend self
end


puts Government.new.metaclass.superclass_chain.inspect
# => [#<PrependedModule People>, Government, Object, #<IncludedModule
Kernel>] <----- looks good, but...
puts Government.new.power
# => belongs to government <---- ...is this right? ;)



So, I actually have two questions:
1) Is it a bug?
2) If it has been done intentionally, then is there better way
manipulate superclass chain?

Thanks,
Daniel Vartanov.
Reply all
Reply to author
Forward
0 new messages