# Current version in core
  def method_defined?(sym)
    sym = normalize_name(sym)
    m = find_method_in_hierarchy sym
    m &&= Tuple[:public, m] unless m.is_a? Tuple
    m ? [:public,:protected].include?(m.first) : false
  end

  # Identical version with lots of prints for current exception
  def test_defined?(sym)
    puts "CHECK 1 EXC: #{$!.inspect}"
    sym = normalize_name(sym)
    puts "CHECK 2 EXC: #{$!.inspect}"
    m = find_method_in_hierarchy sym
    puts "CHECK 3 EXC: #{$!.inspect}"
    m &&= Tuple[:public, m] unless m.is_a? Tuple
    puts "CHECK 4 EXC: #{$!.inspect}"
    ret = m ? [:public,:protected].include?(m.first) : false
    puts "CHECK 5 EXC: #{$!.inspect}"
    ret
  end

# repro
class Z
  def verify
    raise "WTF"
  rescue Object => ex
    puts "Exception was #{$!.inspect} at top of rescue"
    self.class.test_defined?(:to_s)
    puts "Exception was #{$!.inspect} at bottom of rescue"
  end
end

Z.new.verify

prints:


			
Exception was # at top of rescue
CHECK 1 EXC: #
CHECK 2 EXC: #
CHECK 3 EXC: #
CHECK 4 EXC: #
CHECK 5 EXC: nil
Exception was nil at bottom of rescue