diff --git a/CHANGELOG.md b/CHANGELOG.md index 480d9121005e..01f9119c9578 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ Compatibility: * Fix exception for `Fiddle::Handle.new` with a missing library (#2714, @eregon). * Fix arguments implicit type conversion for `BasicObject#instance_eval`, `Module#class_eval`, `Module#module_eval`, `Module#define_method` (@andrykonchin). * Raise `ArgumentError` unconditionally when `Proc.new` is called without a block argument (@andrykonchin). +* Fix `UnboundMethod#hash` to not depend on a module it was retrieved from (#2728, @andrykonchin). Performance: diff --git a/spec/ruby/core/unboundmethod/fixtures/classes.rb b/spec/ruby/core/unboundmethod/fixtures/classes.rb index 46b1c51669a2..1f466e39d86e 100644 --- a/spec/ruby/core/unboundmethod/fixtures/classes.rb +++ b/spec/ruby/core/unboundmethod/fixtures/classes.rb @@ -84,4 +84,14 @@ def overridden; end class C < B def overridden; end end + + module HashSpecs + class SuperClass + def foo + end + end + + class SubClass < SuperClass + end + end end diff --git a/spec/ruby/core/unboundmethod/hash_spec.rb b/spec/ruby/core/unboundmethod/hash_spec.rb index 12dce0020fe2..6888675bc111 100644 --- a/spec/ruby/core/unboundmethod/hash_spec.rb +++ b/spec/ruby/core/unboundmethod/hash_spec.rb @@ -12,4 +12,11 @@ to_s, inspect = Array.instance_method(:to_s), Array.instance_method(:inspect) to_s.hash.should == inspect.hash end + + it "equals a hash of the same method in the superclass" do + foo_in_superclass = UnboundMethodSpecs::HashSpecs::SuperClass.instance_method(:foo) + foo = UnboundMethodSpecs::HashSpecs::SubClass.instance_method(:foo) + + foo.hash.should == foo_in_superclass.hash + end end diff --git a/src/main/java/org/truffleruby/core/method/UnboundMethodNodes.java b/src/main/java/org/truffleruby/core/method/UnboundMethodNodes.java index db54560350e8..10ea2fa9d237 100644 --- a/src/main/java/org/truffleruby/core/method/UnboundMethodNodes.java +++ b/src/main/java/org/truffleruby/core/method/UnboundMethodNodes.java @@ -121,7 +121,6 @@ public abstract static class HashNode extends CoreMethodArrayArgumentsNode { protected long hash(RubyUnboundMethod rubyMethod) { final InternalMethod method = rubyMethod.method; long h = getContext().getHashing(this).start(method.getDeclaringModule().hashCode()); - h = Hashing.update(h, rubyMethod.origin.hashCode()); h = Hashing.update(h, MethodNodes.hashInternalMethod(method)); return Hashing.end(h); }