# 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 #<RuntimeError: WTF> at top of rescue
CHECK 1 EXC: #<RuntimeError: WTF>
CHECK 2 EXC: #<RuntimeError: WTF>
CHECK 3 EXC: #<RuntimeError: WTF>
CHECK 4 EXC: #<RuntimeError: WTF>
CHECK 5 EXC: nil
Exception was nil at bottom of rescue