catch receives a RuntimeException rather than the expected checked exception
Description
Environment
Attachments
Activity

CLJ-855-sneaky-throw.patch applied. Thanks Ben!

Another option, not to make things even more complicated, is to revert the original commit. Perhaps I'm missing the rationale, but...
Checked exceptions are irrelevant to Clojure code, since they are a fabrication of the Java compiler.
Using Clojure code from the Java side could be confusing if you call invoke on IFn and get a checked exception even though it is not declared with a throws clause. It is also confusing to get checked exceptions wrapped in one or more layers of RTEs. Was it not sufficient the way it was before having IFn declare "throws Exception"?

CLJ-855-sneaky-throw.patch
Using "sneaky throw" allows us to effectively rethrow checked exceptions without needing to declare or catch them. In effect, we're back to where we were before wrapping them all up in RTEs (8fda34e4c77...), but without needing to pollute seemingly every method signature in the Java portion of Clojure core with "throws Exception"
This patch was less work than I expected (thanks be to sed) but I'm not as confident in its correctness as I am in that of the try-unwrap variant. I can't claim to have really groked Clojure's approach to exceptions.
I don't understand why Reflector gives preference to rethrowing the cause of the exception it catches (especially now that we're no longer wrapping all over the place.)
I also don't understand why Var.dissoc returns the exception it catches rather than throwing it. (I've left a big fat TODO comment there, which should go from any final version of this patch, should it be accepted.)

CLJ-855-try-unwraps.patch:
Teaches the Java portion of Clojure core to use
WrappedException
(aRuntimeException
) when wrapping checked exceptions for re-throwing.Changes
try
to transparently unwrap (only!)WrappedException
, passing the cause on to be handled by one of its catch clauses. This appears to solve CLJ-855.The original behavior of the try special form (no transparent unwrapping) is still available under the name
try*
.

I've added a unit test which provokes this issue in the Reflector, as opposed to in the Compiler by way of eval. You can browse it here:
https://github.com/bpsm/clojure/commits/CLJ-855
I've refined my patch using the "try unwraps" strategy. The refined patch renames Clojure's try
special form to try*
and provides try
with transparent unwrapping as a macro on top of try*
. The curious may look here:
https://github.com/bpsm/clojure/commits/CLJ-855-try-unwraps
I'll post new patches after I've had some sleep.
I intend to try my hand at the "sneaky throws" strategy that seems to be all the rage here. My experimentation with Herwig's patch showed that it will require investigating some failing unit tests. I believe it will prove a more invasive change than "try unwraps", but may be worth it. A nice challenge.
Details
Details
Assignee

Reporter

Approval
Patch
Priority

Expressions passed to try that trigger the use of clojure.lang.Reflector result in their thrown checked exceptions being wrapped in RuntimeException. As a result, the subsequent set of catches won't switch on the expected checked exception.
Attached: patch for regression test that exposes the problem
Clojure ML Thread: https://groups.google.com/forum/#!topic/clojure/I5l1YHVMgkI/discussion
Introduced: https://github.com/clojure/clojure/commit/8fda34e4c77cac079b711da59d5fe49b74605553