From: "ioquatix (Samuel Williams)" Date: 2021-08-20T01:09:35+00:00 Subject: [ruby-core:105019] [Ruby master Feature#18083] Capture error in ensure block. Issue #18083 has been updated by ioquatix (Samuel Williams). > the exception that happens inside is not a proof the resource is at fault, it could be anything, including a NoMemoryError or a SystemStackError for instance (which e.g. could be due to a bug in the block, not related to the resource at all). Yes, it's a fair assessment. But the key point is there is a different from normal exit (which can include `throw`) and exceptional exit (exception was raised during user code). The reality is, as shown by the examples, lots of code does need to make this differentiation. > You literally want to test "any Ruby exception" or "any other exit from this block", and then rescue Exception just makes sense. Actually, I'm less concerned about the "any Ruby exception" and more concerned with splitting execution between "normal code flow" and "exceptional code flow", and even that is just as an example. Clearly, lots of people **are** using `$!` in an unsafe way, and that's the key point I want to fix. My initial proposal is one way to fix it, by introducing explicit `ensure => error`. However, I agree with Matz, that it can be considered kind of ugly. But if that's true, why don't we get rid of `$!`, surely every case for `$!` can be better handled by explicit `rescue`? If not, why is `$!` necessary? If we can answer that question, then I think we will know what path to take. Personally, I'd vote for the path to get rid of `$!` because I do agree with Matz that its fundamentally pretty ugly both sematically, as well as practically. I looked at a lot of code that uses `$!` and it's often used as a poor replacement for the implicit exception `cause` argument, or for implicit passing error information between code where it should really be explicit. ---------------------------------------- Feature #18083: Capture error in ensure block. https://bugs.ruby-lang.org/issues/18083#change-93421 * Author: ioquatix (Samuel Williams) * Status: Open * Priority: Normal ---------------------------------------- As discussed in https://bugs.ruby-lang.org/issues/15567 there are some tricky edge cases. As a general model, something like the following would be incredibly useful: ``` ruby begin ... ensure => error pp "error occurred" if error end ``` Currently you can get similar behaviour like this: ``` ruby begin ... rescue Exception => error raise ensure pp "error occurred" if error end ``` The limitation of this approach is it only works if you don't need any other `rescue` clause. Otherwise, it may not work as expected or require extra care. Also, Rubocop will complain about it. Using `$!` can be buggy if you call some method from `rescue` or `ensure` clause, since it would be set already. It was discussed extensively in https://bugs.ruby-lang.org/issues/15567 if you want more details. -- https://bugs.ruby-lang.org/ Unsubscribe: