Exception transparency

Nathan Bryant nathan.bryant at linkshare.com
Tue Jun 8 17:35:39 PDT 2010


Hmm,

public class Foo<E> {
  void bar(Func<E> f) throws E;
}

Foo<IOException | ServletException> foo;

Func<FileNotFoundException | ServletException> baz;
Foo.bar(baz); <-- covariant conversion - baz is widened. No problem
right?


Foo<IOException> y
Foo<Exception> x = y // this assignment is also a widening conversion,
so seems ok at first blush

But then:

x.bar(some Func<Exception>) // really invoked on y, undermines type
system.

But then, we can't do this either - clearly unsafe:

Foo<FileNotFoundException> = y;

But <E> should really appear as a method type parameter not a class type
parameter - it's where it belongs:


public class Foo<T> {
  void <E> bar(Func<T, E> f) throws E;
}


-----Original Message-----
From: lambda-dev-bounces at openjdk.java.net
[mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Neal Gafter
Sent: Tuesday, June 08, 2010 7:45 PM
To: Alex Buckley
Cc: lambda-dev at openjdk.java.net
Subject: Re: Exception transparency

On Tue, Jun 8, 2010 at 3:54 PM, Alex Buckley
<alex.buckley at oracle.com>wrote:

> 2) Denotation of disjunctive types. We allow them only in an exception
> type argument "a.m<throws X|Y>(..)", "new Foo<String, throws X|Y>()",
> etc. In particular, not as the bound of an exception type parameter.
> Moreover, exception type parameters "<throws E> void m();" may only be
> used in exception type arguments (and throws clauses), not as "bare"
> types. With these restrictions, exception type arguments are
covariant,
> which is nice. Without these restrictions, you could do this:
>
> interface Function<throws E> { void m(E e); }
> Function<throws IOException> e = #(IOException e){...};
> Function<throws Exception>   f = e;
> try { f.(new Exception()); /* Oops */ } catch (Exception ex) {}
>
> (Actually, I guess we could preserve covariant exception type
arguments
> by banning exception type parameters from appearing in contravariant
> locations like method parameters.)
>

Sounds like you're trying to add declaration-site variance to Java (at
least
for these type parameters).  It isn't clear how you intend that to work.

Can Function<throws E> appear in an argument position of a method, where
E
is a throws-type-parameter of the class containing the method?  If so,
you've undermined exception safety.  If not, you're disallowing a
likely-common programming technique (for example a method like
collection.each).  The problem is that the type parameter has to be
contravariant in this case, but you appear to be proposing to make them
uniformly covariant.

I think your best bet is to NOT have any special variant behavior for
these
type parameters.  Wildcards already serve that purpose for SAMs, and
function types can be made naturally variant without either wildcards or
undermining exception safety.

-Neal



More information about the lambda-dev mailing list