Effect cases in switch
Brian Goetz
brian.goetz at oracle.com
Tue Dec 19 00:34:57 UTC 2023
Turning to Remi's other comments: these are basically about interaction
of this feature with the two throw-related features that came in in Java
7 -- multi-catch and try-with-resources.
In Java 7 we got multi-catch; you can say
catch (E1|E2 e) { ... }
There are several problems with multi-catch; most notably, the typing of
the catch formal (it is a LUB, rather than an intersection type.) This
in turn causes another problem -- a multi-catch that does `throw e`
should fail (since the LUB of two exceptions may well not be permitted
by the throws clause of the enclosing method, even if both alternatives
are.) So another hack was added when adding multi-catch; that if the
operand of `throw` is an effectively-final catch formal, it is allowed.
Separately, some day we may want to make the operand of a catch clause a
pattern, and not just a declaration of a local variable whose type
extends Throwable. This would be useful when we add deconstructors that
support exception chaining:
catch (RuntimeException(IOException e)): ...
But it is far from clear that we want (a) to support union type patterns
or (b) if we did, we want the syntax to be `A|B e`. We will surely have
to navigate this when we get to the point where we consider making
`catch` a pattern-aware context. Presumably, once we address this for
`catch`, the story for `case throws` will follow. But it is not require
that we mirror the behavior of `catch` in `case throws`, any more than
we were forced to do constant patterns when we did patterns in switch
(even though you can say `case 0`.) So I think we do not have to solve
this now, maybe we will address it later in conjunction with catch
clauses, and maybe we never will, and all of those outcomes are OK.
Turning to try-with-resources; there's an alternate form of the `try`
header which can declare one or more resources:
try (R r = e)
When this is present, one or more implicit finally clauses will ensure
that the close() method is called.
Does this mean than an exceptions-aware switch has to do the same? I
think the answer is a pretty clear "no". In a switch:
switch (f(n)) { ... }
where evaluation of f(n) might throw, we _already_ expect f to have
cleaned up any resources it opened, before returning. There is no need
for switch to do more. The reason this case is different is that the
TWR header is opening a resource that the entirety of the try block
needs to be able to operate on; in the case of a single-expression
selector, it's a different story.
So I think the answer to the first is "maybe, someday" and the second is
"nope".
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20231218/cf6c106c/attachment-0001.htm>
More information about the amber-spec-experts
mailing list