<!-- 
RSS generated by JIRA (4.4#649-r158309) at Sat May 25 11:37:06 CDT 2013

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary add field=key&field=summary to the URL of your request.
For example:
http://dev.clojure.org/jira/si/jira.issueviews:issue-xml/CLJ-855/CLJ-855.xml?field=key&field=summary
-->
<rss version="0.92" >
<channel>
    <title>Clojure JIRA</title>
    <link>http://dev.clojure.org/jira</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>4.4</version>
        <build-number>649</build-number>
        <build-date>25-07-2011</build-date>
    </build-info>

<item>
            <title>[CLJ-855] catch receives a RuntimeException rather than the expected checked exception</title>
                <link>http://dev.clojure.org/jira/browse/CLJ-855</link>
                <project id="10010" key="CLJ">Clojure</project>
                        <description>&lt;p&gt;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&apos;t switch on the expected checked exception.&lt;/p&gt;


&lt;p&gt;Attached: patch for regression test that exposes the problem&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-none&quot;&gt;(defn- get-exception [expression]
  (try (eval expression)
    nil
    (catch java.lang.Throwable t
      t)))

(deftest catch-receives-checked-exception
  (are [expression expected-exception] (= expected-exception
                                          (type (get-exception expression)))
    &quot;Eh, I&apos;m pretty safe&quot; nil
    &apos;(java.io.FileReader. &quot;CAFEBABEx0/idonotexist&quot;) java.io.FileNotFoundException)) ; fails&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Clojure ML Thread: &lt;a href=&quot;https://groups.google.com/forum/#!topic/clojure/I5l1YHVMgkI/discussion&quot;&gt;https://groups.google.com/forum/#!topic/clojure/I5l1YHVMgkI/discussion&lt;/a&gt;&lt;br/&gt;
Introduced: &lt;a href=&quot;https://github.com/clojure/clojure/commit/8fda34e4c77cac079b711da59d5fe49b74605553&quot;&gt;https://github.com/clojure/clojure/commit/8fda34e4c77cac079b711da59d5fe49b74605553&lt;/a&gt;&lt;/p&gt;</description>
                <environment></environment>
            <key id="14692">CLJ-855</key>
            <summary>catch receives a RuntimeException rather than the expected checked exception</summary>
                <type id="1" iconUrl="http://dev.clojure.org/jira/images/icons/bug.gif">Defect</type>
                                <priority id="3" iconUrl="http://dev.clojure.org/jira/images/icons/priority_major.gif">Major</priority>
                    <status id="6" iconUrl="http://dev.clojure.org/jira/images/icons/status_closed.gif">Closed</status>
                    <resolution id="1">Completed</resolution>
                                <assignee username="bsmith.occs@gmail.com">Ben Smith-Mannschott</assignee>
                                <reporter username="pmbauer">Paul Michael Bauer</reporter>
                        <labels>
                    </labels>
                <created>Tue, 11 Oct 2011 20:44:25 -0500</created>
                <updated>Fri, 1 Mar 2013 12:47:00 -0600</updated>
                    <resolved>Wed, 29 Feb 2012 15:07:14 -0600</resolved>
                            <version>Release 1.3</version>
                                <fixVersion>Release 1.4</fixVersion>
                                        <due></due>
                    <votes>2</votes>
                        <watches>5</watches>
                        <comments>
                    <comment id="26942" author="bsmith.occs@gmail.com" created="Wed, 12 Oct 2011 02:06:09 -0500"  >&lt;p&gt;(marked up code snippet in description to display as code.)&lt;/p&gt;</comment>
                    <comment id="26945" author="bsmith.occs@gmail.com" created="Wed, 12 Oct 2011 16:23:34 -0500"  >&lt;p&gt;(This incorporates a slightly modified version of Paul Michael Bauer&apos;s&lt;br/&gt;
checked-exception-regression-test patch.)&lt;/p&gt;

&lt;p&gt;ClojureException is an RTE. RTEs that originate from Clojure all are&lt;br/&gt;
of this type. This isn&apos;t strictly necessary for this proof of concept,&lt;br/&gt;
but it seemed prudent since it seems that the lack of specificity resulting&lt;br/&gt;
from using plain RTE everywhere got us into this mess in the first place.&lt;/p&gt;

&lt;p&gt;WrappedException is a ClojureException. It is used when Clojure is&lt;br/&gt;
wrapping the underlying cause to work around Java&apos;s obsession with&lt;br/&gt;
checked exceptions. It&apos;s &lt;b&gt;always&lt;/b&gt; the underlying cause of&lt;br/&gt;
WrappedException that is relevant to catchers.&lt;/p&gt;

&lt;p&gt;Util.runtimeException(s) now returns a ClojureException&lt;br/&gt;
This is not strictly necessary for this patch to work&lt;/p&gt;

&lt;p&gt;Util.runtimeException(s,e) now returns a WrappedException.&lt;/p&gt;

&lt;p&gt;Util.runtimeException(e) now retuns a WrappedException when e is not&lt;br/&gt;
already a RuntimeException.&lt;/p&gt;

&lt;p&gt;clojure.core/treye is a macro built on top of the compiler-provided&lt;br/&gt;
special form try. (A &lt;b&gt;real&lt;/b&gt; solution to this problem would involve&lt;br/&gt;
altering the try special form itself, but this ist just a trial balloon&lt;br/&gt;
to figure out if this is the right way to go.)&lt;/p&gt;

&lt;p&gt;Paul Michael Bauer&apos;s try_catch.clj uses treye in place of try and passes.&lt;/p&gt;</comment>
                    <comment id="26951" author="hiredman" created="Wed, 12 Oct 2011 17:34:35 -0500"  >&lt;p&gt;&amp;gt;  &lt;a href=&quot;http://james-iry.blogspot.com/2010/08/on-removing-java-checked-exceptions-by.html&quot;&gt;http://james-iry.blogspot.com/2010/08/on-removing-java-checked-exceptions-by.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;seems like refactoring Reflector.java to rethrow using this approach&lt;br/&gt;
is preferable to some wrapping/unwrapping scheme&lt;/p&gt;</comment>
                    <comment id="26952" author="pmbauer" created="Wed, 12 Oct 2011 17:42:48 -0500"  >&lt;p&gt;(edit: missed Kevin&apos;s post)&lt;br/&gt;
&lt;a href=&quot;http://james-iry.blogspot.com/2010/08/on-removing-java-checked-exceptions-by.html&quot;&gt;http://james-iry.blogspot.com/2010/08/on-removing-java-checked-exceptions-by.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I&apos;d rather see Reflector.java modified to use this &quot;chucking&quot; technique than have a special try form that specially unwraps an exception and re-throws.&lt;/p&gt;

&lt;p&gt;Maybe there&apos;s a need for WrappedException, but since it&apos;s not immediately necessary if we fix Reflector, then I&apos;d rather see it in a separate commit.&lt;/p&gt;

&lt;p&gt;(I&apos;m swamped at work today and don&apos;t have time to fix Reflector myself right now)&lt;/p&gt;</comment>
                    <comment id="26954" author="bendlas" created="Wed, 12 Oct 2011 21:27:02 -0500"  >&lt;p&gt;I added Util.throwUnchecked and Util.throwCause (also Util.declareThrows and Util.invokeThrowing) as justified in &lt;a href=&quot;https://groups.google.com/d/msg/clojure-dev/4QynV81W0Qk/rIN9fYUK-AkJ&quot;&gt;https://groups.google.com/d/msg/clojure-dev/4QynV81W0Qk/rIN9fYUK-AkJ&lt;/a&gt;&lt;br/&gt;
I&apos;ve used this to fix the invoke* methods in Reflector. Please review.&lt;/p&gt;

&lt;p&gt;There are a lot of other instances in the code, where checked exceptions are runtime-ified, but that&apos;s a separate issue.&lt;/p&gt;</comment>
                    <comment id="26956" author="bsmith.occs@gmail.com" created="Thu, 13 Oct 2011 01:07:55 -0500"  >&lt;p&gt;Applying the patch &lt;a href=&quot;http://dev.clojure.org/jira/browse/CLJ-855&quot; title=&quot;catch receives a RuntimeException rather than the expected checked exception&quot;&gt;&lt;del&gt;CLJ-855&lt;/del&gt;&lt;/a&gt;_throw_undeclared_checked.patch produces java that can not be compiled in four places:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;&lt;span class=&quot;code-keyword&quot;&gt;catch&lt;/span&gt; (Exception e)
  {
  Util.throwCause(e);
  }&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This leaves the compiler complaining about a missing &lt;tt&gt;return&lt;/tt&gt;.&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;&lt;span class=&quot;code-keyword&quot;&gt;catch&lt;/span&gt; (Exception e) 
  {
  &lt;span class=&quot;code-keyword&quot;&gt;return&lt;/span&gt; Util.throwCause(e);
  }&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;compiles.&lt;/p&gt;

&lt;p&gt;Also, the patch doesn&apos;t actually cause try_catch.clj to pass. I suspect the RuntimeException being caught by try_catch.clj is not, in fact, originating from one of the four points you have corrected. (Indeed, I discovered something similar when working on my patch, but it was late, and I ended up solving it in such a way that I didn&apos;t have to find the actual source of this particular wrapped exception.) I&apos;m still investigating...&lt;/p&gt;</comment>
                    <comment id="26957" author="pmbauer" created="Thu, 13 Oct 2011 01:11:32 -0500"  >&lt;p&gt;@Herwig thanks.&lt;br/&gt;
A few issues with the patch:&lt;br/&gt;
1. doesn&apos;t build. Use &quot;return Util.throwCause(...)&quot; instead of just &quot;Util.throwCause(...)&quot;  Otherwise the compiler complains about a missing return statement.&lt;br/&gt;
2. could you observe the whitespace conventions in the rest of the Java source files (tabs for indentation)?&lt;br/&gt;
3. The semantics of throwCause are different than before.  Previously, we threw the Throwable only if t wasnt 1) null 2) an instance of Exception or 3) instance of Error.  Subtle, and maybe it&apos;s a non-issue?&lt;/p&gt;</comment>
                    <comment id="26958" author="bsmith.occs@gmail.com" created="Thu, 13 Oct 2011 01:21:15 -0500"  >&lt;p&gt;The wrapping RuntimeException that causes try_catch.clj to fail is actually coming out of &lt;tt&gt;Compiler.eval(Object,boolean)&lt;/tt&gt; without involving Reflector at all. &lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://dev.clojure.org/jira/browse/CLJ-855&quot; title=&quot;catch receives a RuntimeException rather than the expected checked exception&quot;&gt;&lt;del&gt;CLJ-855&lt;/del&gt;&lt;/a&gt; appears to be about more than just oddness in Reflector.java. My guess is it requires a more general solution.&lt;/p&gt;</comment>
                    <comment id="26959" author="bendlas" created="Thu, 13 Oct 2011 10:06:22 -0500"  >&lt;p&gt;Oh, it seems I was too fast with the second commit. That&apos;s kind of embarrassing, sorry about that.&lt;br/&gt;
Please only consider the first commit of the patch, where I implemented the chucked exception helpers.&lt;/p&gt;

&lt;p&gt;I had considered the issue with only rethrowing causes that are instances of Exception or Error. I dismissed it, because I considered it an artifact of not having chucked exceptions before. The throwCause is for unwrapping InvokationTargetExceptions and such. The only case where it could unwrap differently than the original code, is when having causes other than Exception or Error. i.e. a third subclass of Throwable, which is mostly unheard of (but should probably be unwrapped too).&lt;/p&gt;

&lt;p&gt;Rich, do you remember, if there are any further implications to the catch idiom in Reflector?&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;&lt;span class=&quot;code-keyword&quot;&gt;catch&lt;/span&gt;(Exception e)
    {
    &lt;span class=&quot;code-keyword&quot;&gt;if&lt;/span&gt;(e.getCause() &lt;span class=&quot;code-keyword&quot;&gt;instanceof&lt;/span&gt; Exception)
      &lt;span class=&quot;code-keyword&quot;&gt;throw&lt;/span&gt; Util.runtimeException(e.getCause());
    &lt;span class=&quot;code-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;code-keyword&quot;&gt;if&lt;/span&gt;(e.getCause() &lt;span class=&quot;code-keyword&quot;&gt;instanceof&lt;/span&gt; Error)
      &lt;span class=&quot;code-keyword&quot;&gt;throw&lt;/span&gt; (Error) e.getCause();
    &lt;span class=&quot;code-keyword&quot;&gt;throw&lt;/span&gt; Util.runtimeException(e);
    }&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;hr /&gt;

&lt;p&gt;Regarding the actual source of the wrapping (Compiler.eval): It showed up in my `rgrep catch(Exception`, but I considered it part of the &quot;other issue&quot; (of general refactoring). In fact, I think it won&apos;t show up, mostly, because people noticed this issue when having &lt;b&gt;reflective calls&lt;/b&gt; in clojure code, &lt;b&gt;which don&apos;t use eval&lt;/b&gt;. So the test case is probably testing another source of RuntimeException wrapping.&lt;/p&gt;

&lt;p&gt;This shows, IMO, that most occurrences of `throw Util.runtimeException` should be replaced by `return Util.throwUnchecked`, but probably not all. This will require some scrutiny and careful testing. We need to consider every `catch (Exception e)` in the clj code base. &lt;/p&gt;

&lt;p&gt;I&apos;ll take a stab at it, tonight (CEST), also testing properly this time (sorry again, had some troubles with my build system yesterday)&lt;/p&gt;</comment>
                    <comment id="26962" author="bsmith.occs@gmail.com" created="Thu, 13 Oct 2011 16:21:51 -0500"  >&lt;p&gt;I&apos;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:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/bpsm/clojure/commits/CLJ-855&quot;&gt;https://github.com/bpsm/clojure/commits/CLJ-855&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I&apos;ve refined my patch using the &quot;try unwraps&quot; strategy. The refined patch renames Clojure&apos;s &lt;tt&gt;try&lt;/tt&gt; special form to &lt;tt&gt;try*&lt;/tt&gt; and provides &lt;tt&gt;try&lt;/tt&gt; with transparent unwrapping as a macro on top of &lt;tt&gt;try*&lt;/tt&gt;. The curious may look here: &lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/bpsm/clojure/commits/CLJ-855-try-unwraps&quot;&gt;https://github.com/bpsm/clojure/commits/CLJ-855-try-unwraps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I&apos;ll post new patches after I&apos;ve had some sleep.&lt;/p&gt;

&lt;p&gt;I intend to try my hand at the &quot;sneaky throws&quot; strategy that seems to be all the rage here. &lt;img class=&quot;emoticon&quot; src=&quot;http://dev.clojure.org/jira/images/icons/emoticons/tongue.gif&quot; height=&quot;20&quot; width=&quot;20&quot; align=&quot;absmiddle&quot; alt=&quot;&quot; border=&quot;0&quot;/&gt; My experimentation with Herwig&apos;s patch showed that it will require investigating some failing unit tests. I believe it will prove a more invasive change than &quot;try unwraps&quot;, but may be worth it. A nice challenge.&lt;/p&gt;


</comment>
                    <comment id="26971" author="bsmith.occs@gmail.com" created="Fri, 14 Oct 2011 00:04:43 -0500"  >&lt;p&gt;&lt;a href=&quot;http://dev.clojure.org/jira/browse/CLJ-855&quot; title=&quot;catch receives a RuntimeException rather than the expected checked exception&quot;&gt;&lt;del&gt;CLJ-855&lt;/del&gt;&lt;/a&gt;-try-unwraps.patch:&lt;/p&gt;

&lt;ol&gt;
	&lt;li&gt;Teaches the Java portion of Clojure core to use &lt;tt&gt;WrappedException&lt;/tt&gt; (a &lt;tt&gt;RuntimeException&lt;/tt&gt;) when wrapping checked exceptions for re-throwing.&lt;/li&gt;
	&lt;li&gt;Changes &lt;tt&gt;try&lt;/tt&gt; to transparently unwrap (only!) &lt;tt&gt;WrappedException&lt;/tt&gt;, passing the cause on to be handled by one of its catch clauses. This appears to solve &lt;a href=&quot;http://dev.clojure.org/jira/browse/CLJ-855&quot; title=&quot;catch receives a RuntimeException rather than the expected checked exception&quot;&gt;&lt;del&gt;CLJ-855&lt;/del&gt;&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;The original behavior of the try special form (no transparent unwrapping) is still available under the name &lt;tt&gt;try*&lt;/tt&gt;.&lt;/li&gt;
&lt;/ol&gt;


</comment>
                    <comment id="26981" author="bsmith.occs@gmail.com" created="Fri, 14 Oct 2011 14:34:30 -0500"  >&lt;p&gt;&lt;a href=&quot;http://dev.clojure.org/jira/browse/CLJ-855&quot; title=&quot;catch receives a RuntimeException rather than the expected checked exception&quot;&gt;&lt;del&gt;CLJ-855&lt;/del&gt;&lt;/a&gt;-sneaky-throw.patch&lt;/p&gt;

&lt;p&gt;Using &quot;sneaky throw&quot; allows us to effectively rethrow checked exceptions without needing to declare or catch them. In effect, we&apos;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 &quot;throws Exception&quot;&lt;/p&gt;

&lt;p&gt;This patch was less work than I expected (thanks be to sed) but I&apos;m not as confident in its correctness as I am in that of the try-unwrap variant. I can&apos;t claim to have really groked Clojure&apos;s approach to exceptions.&lt;/p&gt;

&lt;p&gt;I don&apos;t understand why Reflector gives preference to rethrowing the cause of the exception it catches (especially now that we&apos;re no longer wrapping all over the place.)&lt;/p&gt;

&lt;p&gt;I also don&apos;t understand why Var.dissoc returns the exception it catches rather than throwing it. (I&apos;ve left a big fat TODO comment there, which should go from any final version of this patch, should it be accepted.)&lt;/p&gt;</comment>
                    <comment id="27705" author="pjstadig" created="Fri, 10 Feb 2012 09:08:01 -0600"  >&lt;p&gt;Another option, not to make things even more complicated, is to revert the original commit.  Perhaps I&apos;m missing the rationale, but...&lt;/p&gt;

&lt;p&gt;Checked exceptions are irrelevant to Clojure code, since they are a fabrication of the Java compiler.&lt;/p&gt;

&lt;p&gt;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 &quot;throws Exception&quot;?&lt;/p&gt;</comment>
                    <comment id="27893" author="richhickey" created="Wed, 29 Feb 2012 15:06:50 -0600"  >&lt;p&gt;&lt;a href=&quot;http://dev.clojure.org/jira/browse/CLJ-855&quot; title=&quot;catch receives a RuntimeException rather than the expected checked exception&quot;&gt;&lt;del&gt;CLJ-855&lt;/del&gt;&lt;/a&gt;-sneaky-throw.patch applied. Thanks Ben!&lt;/p&gt;</comment>
                </comments>
                    <attachments>
                    <attachment id="10380" name="checked-exception-regression-test.diff" size="2174" author="pmbauer" created="Tue, 11 Oct 2011 20:44:26 -0500" />
                    <attachment id="10395" name="CLJ-855-sneaky-throw.patch" size="22772" author="bsmith.occs@gmail.com" created="Fri, 14 Oct 2011 14:34:30 -0500" />
                    <attachment id="10384" name="CLJ-855_throw_undeclared_checked.patch" size="4969" author="bendlas" created="Wed, 12 Oct 2011 21:27:02 -0500" />
                    <attachment id="10390" name="CLJ-855-try-unwraps.patch" size="17047" author="bsmith.occs@gmail.com" created="Fri, 14 Oct 2011 00:04:43 -0500" />
                </attachments>
            <subtasks>
        </subtasks>
                <customfields>
                                <customfield id="customfield_10002" key="com.atlassian.jira.plugin.system.customfieldtypes:select">
                <customfieldname>Approval</customfieldname>
                <customfieldvalues>
                        <customfieldvalue key="10007">Ok</customfieldvalue>

                </customfieldvalues>
            </customfield>
                                                                                    <customfield id="customfield_10010" key="com.pyxis.greenhopper.jira:gh-global-rank">
                <customfieldname>Global Rank</customfieldname>
                <customfieldvalues>
                    
                </customfieldvalues>
            </customfield>
                                            <customfield id="customfield_10000" key="com.atlassian.jira.plugin.system.customfieldtypes:select">
                <customfieldname>Patch</customfieldname>
                <customfieldvalues>
                        <customfieldvalue key="10002">Code and Test</customfieldvalue>

                </customfieldvalues>
            </customfield>
                                                                                        </customfields>
    </item>
</channel>
</rss>