[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-lambda-dev
Subject:    lambda inference bug
From:       forax () univ-mlv ! fr (=?ISO-8859-1?Q?R=E9mi_Forax?=)
Date:       2011-09-05 16:38:17
Message-ID: 4E64FAF9.1050103 () univ-mlv ! fr
[Download RAW message or body]

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


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic