summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proc.c2
-rw-r--r--spec/ruby/core/unboundmethod/equal_value_spec.rb30
-rw-r--r--spec/ruby/core/unboundmethod/fixtures/classes.rb16
-rw-r--r--test/ruby/test_method.rb14
4 files changed, 62 insertions, 0 deletions
diff --git a/proc.c b/proc.c
index 5b5c2f359b..babc45d790 100644
--- a/proc.c
+++ b/proc.c
@@ -1844,6 +1844,8 @@ method_eq(VALUE method, VALUE other)
klass1 = method_entry_defined_class(m1->me);
klass2 = method_entry_defined_class(m2->me);
+ if (RB_TYPE_P(klass1, T_ICLASS)) klass1 = RBASIC_CLASS(klass1);
+ if (RB_TYPE_P(klass2, T_ICLASS)) klass2 = RBASIC_CLASS(klass2);
if (!rb_method_entry_eq(m1->me, m2->me) ||
klass1 != klass2 ||
diff --git a/spec/ruby/core/unboundmethod/equal_value_spec.rb b/spec/ruby/core/unboundmethod/equal_value_spec.rb
index 036c6b7f8c..a9d79f1484 100644
--- a/spec/ruby/core/unboundmethod/equal_value_spec.rb
+++ b/spec/ruby/core/unboundmethod/equal_value_spec.rb
@@ -35,6 +35,12 @@ describe "UnboundMethod#==" do
@method_one = UnboundMethodSpecs::Methods.instance_method(:one)
@method_two = UnboundMethodSpecs::Methods.instance_method(:two)
+
+ @mixin = UnboundMethodSpecs::Mixin.instance_method(:mixin_method)
+ @includer_base = UnboundMethodSpecs::IncluderBase.new.method(:mixin_method).unbind
+ @includer_child = UnboundMethodSpecs::IncluderChild.new.method(:mixin_method).unbind
+ @extender_base = UnboundMethodSpecs::ExtenderBase.method(:mixin_method).unbind
+ @extender_child = UnboundMethodSpecs::ExtenderChild.method(:mixin_method).unbind
end
it "returns true if objects refer to the same method" do
@@ -110,6 +116,30 @@ describe "UnboundMethod#==" do
end
end
+ ruby_bug "#21873", ""..."3.4" do
+ it "returns true if same method is present in an object through module inclusion" do
+ (@mixin == @includer_base).should == true
+ (@includer_base == @mixin).should == true
+
+ (@mixin == @includer_child).should == true
+ (@includer_child == @mixin).should == true
+
+ (@includer_base == @includer_child).should == true
+ (@includer_child == @includer_base).should == true
+ end
+
+ it "returns true if same method is present in an object through module extension" do
+ (@mixin == @extender_base).should == true
+ (@extender_base == @mixin).should == true
+
+ (@mixin == @extender_child).should == true
+ (@extender_child == @mixin).should == true
+
+ (@extender_base == @extender_child).should == true
+ (@extender_child == @extender_base).should == true
+ end
+ end
+
it "returns false if both have same Module, same name, identical body but not the same" do
class UnboundMethodSpecs::Methods
def discard_1; :discard; end
diff --git a/spec/ruby/core/unboundmethod/fixtures/classes.rb b/spec/ruby/core/unboundmethod/fixtures/classes.rb
index 28d8e0a965..bb3f7e0849 100644
--- a/spec/ruby/core/unboundmethod/fixtures/classes.rb
+++ b/spec/ruby/core/unboundmethod/fixtures/classes.rb
@@ -80,6 +80,22 @@ module UnboundMethodSpecs
end
end
+ module Mixin
+ def mixin_method; end
+ end
+
+ class IncluderBase
+ include Mixin
+ end
+
+ class IncluderChild < IncluderBase; end
+
+ class ExtenderBase
+ extend Mixin
+ end
+
+ class ExtenderChild < ExtenderBase; end
+
class A
def baz(a, b)
return [__FILE__, self.class]
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index a865f6100b..27765577c7 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -111,6 +111,20 @@ class TestMethod < Test::Unit::TestCase
end
end
+ def test_unbound_method_equality_with_extended_module
+ m = Module.new { def hello; "hello"; end }
+ base = Class.new { extend m }
+ sub = Class.new(base)
+
+ from_module = m.instance_method(:hello)
+ from_base = base.method(:hello).unbind
+ from_sub = sub.method(:hello).unbind
+
+ assert_equal(from_module, from_base)
+ assert_equal(from_module, from_sub)
+ assert_equal(from_base, from_sub)
+ end
+
def test_callee
assert_equal(:test_callee, __method__)
assert_equal(:m, Class.new {def m; __method__; end}.new.m)