The following example shows this nicely:
> Future<String> f = ...
> switch (f.get()) {
> case String s -> process(s);
> case throws ExecutionException(var underlying) -> throw underlying;
> case throws TimeoutException e -> cancel();
> }
Note that I don't get the hate for exceptions. Sometimes, handeling the error somewhere up the callstack is exactly the right solution. The problem was that Java did not have convenient syntax for handeling exceptions at call-site.
FYI: There was also an interesting discussion in the Java mailing lists also going into some implementation details regarding the representing bytecode:
https://mail.openjdk.org/pipermail/amber-spec-experts/2023-D...