Trouble inferring type of lambda
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Aug 23 04:15:07 PDT 2010
On 23/08/10 12:02, Howard Lovatt wrote:
> Hi Mauritzio,
>
> I think it is a bug, like I said in the original post the 'return
> type' is 'NeverReturns' not void, which should be assignable to
> anything (including Integer). Scala and BGGA handle this case, they
> both have a 'NeverReturns' type (Scala and BGGA Nothing).
>
Let me clarify - it is not a bug, according to the current spec; quoting
from the latest formal spec describing lambda conversion [1]:
"A divergent lambda expression such as #(){throw new AssertionError();}
has no return value, and its body completes abruptly by reason of a
throw with an AssertionError object. For the purpose of calculating
the type of the lambda expression, the body of the lambda expression
is void."
[1] -
http://mail.openjdk.java.net/pipermail/lambda-dev/attachments/20100212/af8d2cc5/attachment-0001.txt
Maurizio
> Cheers,
>
> -- Howard.
>
> On 23 August 2010 20:35, Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com> wrote:
>
>> This is not a bug. You are trying to SAM convert the following lambda:
>>
>> #(x) { throws Exception(); }
>>
>> into the following target method:
>>
>> <throws E> Integer call( Integer a1 ) throws E
>>
>> This is not possible, since the lambda expression is inferred to yield
>> 'void' (no return expression found), while the target method returns
>> Integer.
>>
>> Maurizio
>>
>>
>>
>> On 22/08/10 18:45, maurizio cimadamore wrote:
>>
>>> On 22/08/2010 07:09, Howard Lovatt wrote:
>>>
>>>
>>>> For:
>>>>
>>>> public interface Method1<R, A1, throws E> { public R call( A1 a1 )
>>>> throws E; }
>>>>
>>>> and:
>>>>
>>>> public<throws E> void forEach( final Method1<Integer, Integer, E>
>>>> method ) throws E { ... }
>>>>
>>>> The compiler has trouble with:
>>>>
>>>> il.forEach( #( i ) { throw new Exception(); } ); // Need to catch
>>>> checked exception
>>>>
>>>> Giving:
>>>>
>>>> lambdas/Main.java:34: method forEach in class IntList11 cannot be
>>>> applied to given types
>>>> il.forEach( #( i ) { throw new Exception(); } ); // Need to
>>>> catch checked exception
>>>> ^
>>>> required: Method1<Integer,Integer,E>
>>>> found: #void(?)(Exception)
>>>> where E is a type-variable:
>>>> E extends Exception declared in method
>>>> <E>forEach(Method1<Integer,Integer,E>)
>>>>
>>>> Qualifying doesn't help:
>>>>
>>>> Method1<Integer, Integer, Exception> #( i ) { throw new Exception();
>>>> }
>>>>
>>>> It gives:
>>>>
>>>> lambdas/Main.java:34: incompatible types; no instance(s) of type
>>>> variable(s) ? exist so that #void(?)(Exception) conforms to
>>>> Method1<Integer,Integer,Exception>
>>>> il.forEach( Method1<Integer, Integer, Exception> #( i ) { throw
>>>> new Exception(); } ); // Need to catch checked exception
>>>> ^
>>>> required: Method1<Integer,Integer,Exception>
>>>> found: #void(?)(Exception)
>>>>
>>>> Is the problem that the return type isn't expressible? It isn't really
>>>> void, it is 'NeverReturns'.
>>>>
>>>>
>>>>
>>> Uhmm the problem here seems more related with a failure in inference of
>>> the lambda parameter (the '?' that you are seeing). Again it would be
>>> helpful to see the declaration of the receiver class as well as the type
>>> of 'il'.
>>>
>>> Maurizio
>>>
>>>
>>>> -- Howard.
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>
>
More information about the lambda-dev
mailing list