Union types and exception handling

Kłeczek, Michał michal at kleczek.org
Thu May 14 15:19:12 UTC 2020


Thanks for your response. Some thoughts inline.

On 14/05/2020 15:00:30, "Brian Goetz" <brian.goetz at oracle.com> wrote:

>I assume you're trying to get to exception transparency for lambdas: 
>that's a worthy goal.  We've been down this road before.

This is interesting - couldn't find any trace of discussions so I asked 
here.

>
>
>Union types are actually a pretty small part of the story here.  One of 
>the roadblocks you're going to hit is that if you let someone say 
>"throws E", you're going to eventually want to let them say "catch E".  
>But E is erased, so what bytecode are you going to generate?  How are 
>you going to tell an E from another exception?  How do you even know 
>what order it will be allowed to put the catch blocks, since we 
>currently (for good reason) do not allow dominated catch blocks?
Actually I was more thinking about some "lightweight" (whatever that 
means :) ) syntax extension  to what we have today with generic 
exceptions. For the reasons you state I don't think about generic catch.

>
>
>If you want to allow lambdas to throw checked exceptions, you also need 
>a story for keeping the exceptions from escaping the scope of compiler 
>analysis.  The easy case is one like this:
>
>     interface ConsumerEx<T, E throws Exception> {
>         void accept(T arg) throws E;
>     }
>
>     <E extends Exception>
>     void forEach(ConsumerEx<T,E> c) throws E { ... }
>
>Here, you assume that the implementation will just turn around and call 
>the lambda.  But what if the implementation casts the lambda to raw, 
>and stashes it in a static, and calls it later (maybe from another 
>thread)?  Now you've invented another "sneaky throw" vector.
Yes - and this is fine IMHO.
It is no different than what we have today.

>
>
>It gets worse: think Streams.  I might pass all sorts of throwy lambdas 
>to filter() and map(), but they don't get called until I call 
>`forEach()` or `collect()` (or worse, you call `iterator()` and then 
>call `Iterator::next`.)  Capturing this soundly in the type system (an 
>effects system, actually) is no small bit of language engineering.
>
>All of this is orthogonal to the union type / variadic generics part of 
>the problem.
We see more and more voices proposing getting rid of checked exceptions 
entirely but I think something like:

Stream<T, E> {
   <S, E1, E2 extends E | E1> Stream<S, E2> map(Function<T, S, E1> 
mapper);
   Iterator<T, E> iterator();
}

might be a pretty good middle ground.

<E extends IOException | ClassNotFoundException> Object readObject() 
throws E;

would be erased to

Object readObject() throws Exception; //Exception is a lub of IOE and 
CNFE

but would allow the compiler to perform some flow analysis similar to 
what it does today with checked exceptions (isn't the exception list a 
union type in disguise?)

If you have any links to past discussions - I am happy to read through 
all of them.

Michal

>
>
>
>
>
>
>On 5/14/2020 3:56 AM, Kłeczek, Michał wrote:
>>Hello All,
>>
>>I am playing with javac lately looking for a way to implement some 
>>form of union types - along the lines of:
>>
>>interface Function<S, T, E extends Exception> {
>>   T apply(S arg) throws E;
>>}
>>
>>interface Stream<T, E extends Exception> {
>>   // resulting stream is parametrized with a union type
>>   <S, MapperEx extends Exception, ResultEx extends E | MapperEx> 
>>Stream<S, ResultEx> map(Function<? super T, S, MapperEx> mapper);
>>   boolean isEmpty() throws E;
>>}
>>
>><S, T, E extends IOException | ClassNotFoundException> T 
>>foo(Function<S, T, E> f, S arg) throws ClassNotFoundException {
>>   try {
>>     return f.apply(arg);
>>   }
>>   catch (IOException e) {
>>   }
>>}
>>
>>A very limited form of union types is already implemented for 
>>multi-catch clauses and I am wondering
>>if:
>>- it can be reused
>>- anything more general has been discussed/prototyped - is anyone 
>>aware of such efforts?
>>
>>Thanks,
>>Michal
>>
>



More information about the amber-dev mailing list