lambda inference bug
Rémi Forax
forax at univ-mlv.fr
Mon Sep 5 09:38:17 PDT 2011
On 09/05/2011 03:30 PM, Maurizio Cimadamore wrote:
> On 05/09/11 14:11, Rémi Forax wrote:
>> On 09/05/2011 01:11 PM, Maurizio Cimadamore wrote:
>>> Hi,
>>> forget my earlier comment (I misread your example) - this should
>>> indeed compile, as E gets a lower bound from the first actual
>>> argument. This has been now fixed in the lambda-repo.
>>>
>>> Maurizio
>>
>> Hi Maurizio,
>> thank you for the fast fix.
>>
>> Could you explain me the difference between the inference used by
>> default by javac
>> and the complex inference ?
> Leaving lambda aside for a moment (simpler) - suppose you have the
> following method declaration:
>
> <S> void m(List<S> ls) { ... }
>
> and that you want to call 'm' as follows;
>
> m(new ArrayList<>());
>
> in a perfect world where inference in method context would work as
> expected (;-)) there is a problem with the above source: we are
> supposed to infer the type-variable S from the type of the actual
> argument applied to the method; however, the actual type itself needs
> some inference to be performed.
>
> The standard javac policy is to issue an inference error in such cases
> (cyclic inference - see example below with lambdas).
I was thinking to understand until I test.
The code above works, with javac and with eclipse (+java7 patch),
it's infered as ArrayList<Object>, I think it's because when the
inference fails,
the algorithm returns Object (as specified in the JLS).
By example, if S as a bound, it doesn't compile:
<S extends Number> void m(List<S> ls) { ... }
...
m(new ArrayList<>());
> However, I've been working at a more aggressive inference scheme that
> tries to 'unstuck' the inference process in a backward compatible way:
>
> *) first, the type of the actual argument is inferred w/o the expected
> type (i.e. using Object). Thus, the actual is first inferred to be
> ArrayList<Object>
I think, you should use the bound of the type variable here,
but there is still a problem with recursive bound.
>
> *) then, the newly instantiated actual is used to carry on the
> inference of the formal (thus, S == Object).
>
> Note that, while the result is not as specific as we would like it to
> be, on the other hand the compiler would be able to compile this
> example, and to have an answer that would be compatible with what the
> compiler inferred in JDK 7.
>
> With inference of lambda formals, it is sometimes possible to end up
> with a situation that is morally equivalent to the one illustrated
> above - an example is:
>
> interface SAM<X> {
> List<X> m();
> }
>
> class Test {
> <Z> void m(SAM<Z> sz) { }
>
> { m(#{ -> new ArrayList<>() }); }
> }
>
> The above doesn't compile by default - however it can be made to
> compile by enabling the -XDcomplexinference flag.
>
> We still have to decide as to whether this 'aggressive' mode will be
> the default behavior for the javac compiler in JDK 8. We believe this
> could be an advantage esp. if the scope of target type-inference is
> expanded to support inference in method context.
>
> Maurizio
Rémi
More information about the lambda-dev
mailing list