inference of throws type parameters in SAMs
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Oct 31 14:48:20 PDT 2012
On 31/10/12 20:51, Peter Levart wrote:
> On 10/31/2012 06:48 PM, Maurizio Cimadamore wrote:
>> On 31/10/12 17:37, Remi Forax wrote:
>>> On 10/31/2012 06:20 PM, Maurizio Cimadamore wrote:
>>>> On 31/10/12 17:04, Remi Forax wrote:
>>>>> On 10/31/2012 03:53 PM, Dan Smith wrote:
>>>>>> This is on the radar for inference. As you suggest, we would
>>>>>> probably just choose RuntimeException in certain scenarios rather
>>>>>> than using the upper bound.
>>>>>>
>>>>>> We have toyed with some more ambitious ideas for handling
>>>>>> exceptions in lambda bodies, but those won't be part of Java 8.
>>>>>>
>>>>>> —Dan
>>>>> yes, and my fear is that if we choose something different than Object
>>>>> now (like RuntimeException)
>>>>> we will not be able to change the inference algorithm in Java 9.
>>>>> At least with Object as default, we know that currently the inference
>>>>> fails so
>>>>> we can provide a better one without creating incompatibilities.
>>>> I think Object is never a problem - for this kind of issues to show
>>>> up, the inference variable must appear in the throws clause, which
>>>> means it should be at least <: Throwable.
>>> yes, sorry,
>>> s/Object/Throwable
>>>
>>> Choosing the bound of the unconstrained variable if the variable is
>>> used in a throws in not the better choice,
>>> but before we came with a better algorithm, it's a better choice than
>>> RuntimeException because it doesn't
>>> hamper the use of a better algorithm in the future.
>> Yeah - I think that's kinda the choice ahead of us - on the one hand, if
>> we add exception transparency support in the future, it seems like this
>> case should be handle as a result of that work; on the other hand,
>> inferring RuntimeException could be a reasonable compromise, esp. given
>> that the number of incompatibilities that will occur as a result of an
>> inference upgrade would be pretty low (though it's true that when
>> lambdas are available inference variables in the throws clause might
>> become more common...).
>>
>> Maurizio
> Can we elaborate about incompatibilities that will occur as a result
> of later inference upgrade?
>
> If I understood correctly, you are talking about inference upgrade
> that will happen after JDK8 and which will contain exception
> transparency support.
>
> So, unconstrained variable that is used in functional interface and
> appears only in throws declaration of the sole interface method. What
> incompatibilities can it cause if it is inferred now as
> RuntimeException as opposed to upper bound and in a later release as
> something more appropriate like Nothing? Can we imagine an example?
An example would be along the following lines (admittedly convoluted):
interface SAM<X extends Throwable> {
void m() throws X;
}
<Z> List<Z> m(SAM<Z> s) { ... }
g(List<RuntimeException> l) { } //1
g(Object o) { } //2
g(m(()->{})); //resolves to (1) in JDK 8, resolves to (2) in JDK x+1, x
>= 8 ;-)
Maurizio
>
> Regards, Peter
>
>>>> Maurizio
>>> Rémi
>>>
>>>>> Rémi
>>>>>
>>>>>> On Oct 30, 2012, at 10:18 AM, Peter Levart <peter.levart at gmail.com>
>>>>>> wrote:
>>>>>>
>>>>>>> Hi all,
>>>>>>>
>>>>>>> I know this has been discussed before, but a long time has
>>>>>>> passed and
>>>>>>> various inference algorithms have been tried in the meanwhile. So I
>>>>>>> would like to ask whether current state is final. For example if I
>>>>>>> have
>>>>>>> a functional interface like the following:
>>>>>>>
>>>>>>> public interface ThrowingFactory<T, E extends Throwable> {
>>>>>>> T make() throws E;
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> And a "hypothetical" method:
>>>>>>>
>>>>>>> public interface Stream<T> {
>>>>>>> <E extends Throwable> T
>>>>>>> findFirstOrElse(ThrowingFactory<T, E>
>>>>>>> other) throws E;
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> Then the following program compiles OK:
>>>>>>>
>>>>>>> public static void main(String... args) throws IOException
>>>>>>> {
>>>>>>> Stream<String> stream = null;
>>>>>>>
>>>>>>> String first = stream.findFirstOrElse(() -> {throw new
>>>>>>> IOException();});
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> Which indicates that the inference algorithm does it's job
>>>>>>> correctly.
>>>>>>> But the following program:
>>>>>>>
>>>>>>> public static void main(String... args)
>>>>>>> {
>>>>>>> MyStream<String> stream = null;
>>>>>>>
>>>>>>> String first = stream.findFirstOrElse(() -> "NO VALUE");
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> Triggers the compilation failure:
>>>>>>>
>>>>>>> error: unreported exception Throwable; must be caught or declared
>>>>>>> to be
>>>>>>> thrown
>>>>>>> String first = stream.findFirstOrElse(() -> "NO VALUE");
>>>>>>>
>>>>>>>
>>>>>>> Regards, Peter
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> P.S. If this worked, the controversial TypeThatMustNotBeNamed<T>
>>>>>>> which
>>>>>>> is used as return type of 3 Stream methods could be replaced with
>>>>>>> 3*3=9
>>>>>>> Stream methods that would more or less fit the main purpose of
>>>>>>> being
>>>>>>> fluent. For example, current Stream.findFirst() would expand to:
>>>>>>>
>>>>>>> public interface Stream<T> {
>>>>>>> T findFirst() throws NoSuchElementException;
>>>>>>> T findFirstOrElse(T other);
>>>>>>> <E extends Throwable> T
>>>>>>> findFirstOrElse(ThrowingFactory<T, E>
>>>>>>> other) throws E;
>>>>>>> }
>>>>>>>
>>>>>>> Is this to much methods?
>>>>>>>
>>>>>>>
>>>>>>>
>>
>
More information about the lambda-dev
mailing list