1

I'm trying to monkey patch Object and while my tests run fine, I can't load my project with Pry anymore.

Here is the relevant code:

module CoreExtensions
  def instance_values
    instance_variables.each_with_object({}) do |var, hash|
      hash[var[1..-1]] = instance_variable_get(var)
    end
  end

  def ==(other)
    (self.class == other.class) &&
      (instance_values.equal? other.instance_values)
  end
end

Object.include CoreExtensions

Using

pry -r ./core_extentions.rb

leads to this stacktrace:

Error: No live threads left. Deadlock?
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/input_lock.rb:87:in `sleep'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/input_lock.rb:87:in `wait'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/input_lock.rb:87:in `block in enter_interruptible_region'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/input_lock.rb:83:in `synchronize'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/input_lock.rb:83:in `enter_interruptible_region'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/input_lock.rb:110:in `interruptible_region'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:197:in `input_readline'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:190:in `block in read_line'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:129:in `handle_read_errors'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:170:in `read_line'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:98:in `read'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:68:in `block in repl'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:67:in `loop'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:67:in `repl'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:38:in `block in start'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/input_lock.rb:61:in `__with_ownership'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/input_lock.rb:79:in `with_ownership'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:38:in `start'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/repl.rb:15:in `start'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/pry_class.rb:169:in `start'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-byebug-3.3.0/lib/pry-byebug/pry_ext.rb:11:in `start_with_pry_byebug'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/cli.rb:219:in `block in <top (required)>'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/cli.rb:83:in `block in parse_options'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/cli.rb:83:in `each'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/lib/pry/cli.rb:83:in `parse_options'
/home/fap/.rvm/gems/ruby-2.3.0/gems/pry-0.10.3/bin/pry:16:in `<top (required)>' /home/fap/.rvm/gems/ruby-2.3.0/bin/pry:23:in `load'
/home/fap/.rvm/gems/ruby-2.3.0/bin/pry:23:in main
/home/fap/.rvm/gems/ruby-2.3.0/bin/ruby_executable_hooks:15:in `eval'
/home/fap/.rvm/gems/ruby-2.3.0/bin/ruby_executable_hooks:15:in main

The same thing happens when I include my CoreExtentions in the main class.

I read about Pry's input_lock, but I don't understand what produces the deadlock.

Does anyone have an idea why this is happening?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
fap
  • 663
  • 1
  • 5
  • 14
  • 1
    I think you've broken ==. ( for example `x = Object.new; x == x ` produces false – Frederick Cheung Apr 02 '16 at 19:27
  • 2
    I recommend reading the accepted answer to [What's the difference between equal?, eql?, ===, and ==?](https://stackoverflow.com/questions/7156955) because I believe you've misunderstood `equal?`. – cremno Apr 02 '16 at 20:25
  • 1
    `==` is used in so many contexts, I can't see why you'd want to override it for all objects. Why not just give it a custom method name like `my_equals_method()` – max pleaner Apr 02 '16 at 21:04

1 Answers1

1

You have redefined method == for all objects, which is not a good thing.

This comes about from the last line in your question, namely Object.include CoreExtentions

Without that definition, it loads fine.

vgoff
  • 10,980
  • 3
  • 38
  • 56
  • 2
    In particular, you have overridden `BasicObject#==` with an implementation that always returns `false`, it *cannot* possibly ever return `true`. – Jörg W Mittag Apr 03 '16 at 00:48
  • You are right, the posted implementation can never return true. I wanted to provide a default method for structural equality that compares the classes and instance values but I got it wrong. – fap Apr 03 '16 at 02:32
  • I was not aware that calling `include` on `Object` was actually overriding the method in `BasicObject`. Now @JörgWMittag has me doing some testing. – vgoff Apr 03 '16 at 06:47
  • Ah, due to `Object` getting it from the parent class of `BasicObject`. The things we forget to remember. – vgoff Apr 03 '16 at 06:56
  • 2
    Including a mixin basically makes the mixin the parent class. So, `Objecs`'s parent class is `BasicObject`. However, `Object` also mixes in `Kernel`, so the inheritance chain *before* calling `Object.include CoreExtensions` looks like this: `BasicObject` → `Kernel` → `Object`. Afterwards it looks like this: `BasicObject` → `Kernel` → `CoreExtensions` → `Object`. Ergo, all methods defined in `CoreExtensions` override methods defined in `Kernel` and `BasicObject`. The "trick" Ruby uses of injecting mixins into the class hierarchy means that boring standard inheritance rules apply. – Jörg W Mittag Apr 03 '16 at 18:50