Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong with this rescue example?

x = StandardError.new(:hello)
y = StandardError.new(:hello)
x == y # => true
x === y # => true

begin
  raise x
rescue x
  puts "ok" # gets printed
end

begin
  raise x
rescue y
  puts "ok" # doesn't get printed
end

Why isn't the second "ok" printed? I can't figure it out. I've read here that ruby uses the === operator to match exceptions to rescue clauses, but that's ostensibly not the case.

I'm using Ruby 1.9.3

EDIT: So it seems like that after doing raise x, x == y and x === y no longer hold. It seems to because x and y no longer have the same backtrace.

like image 834
Norswap Avatar asked Oct 06 '22 18:10

Norswap


1 Answers

I think that's a bug, or rather an underspecification of Ruby 1.9. Note that Ruby 2.0 raises a

TypeError: class or module required for rescue clause

on lines 8 and 14.

Note that the raise doesn't necessarily do what you think it does, either. When you raise an object, you don't actually raise that object, you raise a new object which is constructed from the object you passed according to these simple rules:

  • if the object responds to exception, call exception on the object and raise the return value
  • if the object is a subclass of Exception, call new and raise the return value
  • otherwise fail
  • also fail if the return value of any of the above methods is not an instance of Exception

So, you are not actually raising x, you are raising x.exception. According to the documentation of Exception#exception x.exception is x, though.

like image 121
Jörg W Mittag Avatar answered Oct 10 '22 03:10

Jörg W Mittag