lambda in result expression of explicitly typed lambda
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Feb 13 14:29:51 UTC 2015
See 15.12.2.2 (I made relevant text in bold):
"An argument expression is considered pertinent to applicability for a
potentially applicable method m unless it has one of the following forms:
An implicitly typed lambda expression (§15.27.1).
An inexact method reference expression (§15.13.1).
*If m is a generic method and the method invocation does not provide
explicit type arguments, an explicitly typed lambda expression or an
exact method reference expression for which the corresponding target
type (as derived from the signature of m) is a type parameter of m.*
*An explicitly typed lambda expression whose body is an expression that
is not pertinent to applicability*.
An explicitly typed lambda expression whose body is a block, where
at least one result expression is not pertinent to applicability.
A parenthesized expression (§15.8.5) whose contained expression is
not pertinent to applicability.
A conditional expression (§15.25) whose second or third operand is
not pertinent to applicability."
Now, the first statement in bold says that a lambda whose target is a
type-parameter of 'm' (foo) is not pertinent to applicability. (1)
The second statement in bold says that if that the body of an explicit
expression lambda is not pertinent to applicability, then the lambda is
also not pertinent to applicability. (2)
So, question:
"is () -> () -> null pertinent to applicability in <T>foo?"
To answer that we need to look at the body of the lambda - so, new question:
"is () -> null pertinent to applicability in <T>foo?"
To answer this, we must first determine the target-type of the lambda,
as per (1). We can safely assume that the target of the full lambda
(above) is Supplier<T>, which means that the target-type of this lambda
is T.
So (1) applies - () -> null has a target T where T is a type-variable of
the generic method 'foo' (whose applicability is being determined).
This means that () -> null is _not_ pertinent to applicability.
Which means () -> () -> null is also _not_ pertinent to applicability.
I don't see anything missing from the spec - if I really had to pick one
thing that is not so crystal-clear, I believe this section is a bit
vague as to what happens when the target of a lambda is the
type-variable of an outer method call.
Maurizio
On 13/02/15 13:47, Anna Kozlova wrote:
> At the applicability check phase of 18.5.1: "C includes, for all i (1 ≤ i ≤ k) where ei is pertinent to applicability,‹ei → Fi θ›."
>
> I treat () -> () -> {} as pertinent to applicability, after that everything goes wrong. If I fix pertinent to applicability check to reject nested lambda, then everything is ok here.
>
> So how to treat nested lambda as not pertinent to applicability?
>
> Thanks!
>
> P.S.
> javac doesn't compile code
> {
> Supplier<Runnable> x = foo(() -> () -> null);
> }
>
> static <T> Supplier<T> foo(Supplier<List<T>> delegate) {
> return null;
> }
> So it's not enough to have return type non proper.
>
> -----Original Message-----
> From: Maurizio Cimadamore [mailto:maurizio.cimadamore at oracle.com]
> Sent: Friday, February 13, 2015 2:27 PM
> To: Anna Kozlova; compiler-dev at openjdk.java.net
> Subject: Re: lambda in result expression of explicitly typed lambda
>
> I guess I'm missing the connection with pertinent to applicability here... anyway, in your example, the lambda is not pertinent to applicability (because, recursively, its nested lambda isn't). This means that, when doing overload resolution, the lambda is ignored - but this doesn't matter here as there's only one 'foo' method, so the compiler picks that as the most specific.
>
> I think your question is more about 'invocation type-inference' which happens _after_ overload resolution (when a most specific method has already been chosen). In this case, the spec says that an additional bunch of constraints should be _set up_ for all arguments that are not pertinent to applicability (and hence for your lambda too). This doesn't mean that the constraints are immediately evaluated, as the dependency analysis in 18.5.2 makes sure that arguments constraints are evaluated only when all input type variables have been inferred to something.
>
> Maurizio
>
> On 13/02/15 12:21, Anna Kozlova wrote:
>> Maurizio,
>>
>> My understanding of "pertinent to applicability" was always incomplete. "An explicitly typed lambda expression whose body is an expression that is not pertinent to applicability" when pertinent to applicability is defined for argument expression of a method call. Should the return type of selected functional type be checked if it is a proper type (or that it should not be the type parameter of the method)? Did I missed it in the spec or can this be added there please?
>>
>> Thanks,
>> Anna
>>
>> -----Original Message-----
>> From: Maurizio Cimadamore [mailto:maurizio.cimadamore at oracle.com]
>> Sent: Thursday, February 12, 2015 11:13 PM
>> To: Anna Kozlova; compiler-dev at openjdk.java.net
>> Subject: Re: lambda in result expression of explicitly typed lambda
>>
>>
>> On 12/02/15 19:51, Anna Kozlova wrote:
>>> Hi,
>>>
>>> Consider the following code:
>>>
>>> {
>>> Supplier<Runnable > x = foo (() -> () -> {});
>>> }
>>>
>>> static <T> Supplier<T> foo(Supplier<T> delegate) {
>>> return null;
>>> }
>>>
>>> At the applicability check phase I expect B2 to contain <() -> {} -> T>, and according to 18.2.1 it reduces to false ("If T is not a functional interface type (§9.8), the constraint reduces to false").
>>> However 8u40 b23 compiles the code just fine, but why?
>> I think it's an issue of timing - i.e. 18.2.1 should not be applied to
>> non-proper types; I believe it should only be applied after you
>> inferred T to be Runnable (form the target) and then incorporated the
>> result into the method target (which then becomes Supplier<Runnable>,
>> and 18.2.1 is happy). The reason as to why 18.2.1 is 'deferred' is
>> buried inside
>> 18.5.2 - long story short, the constraint () -> () -> {} --> Supplier<T> cannot be looked into because it depends on an input inference variable, namely T. Since the constraints formula is not evaluated, 18.2.1 doesn't kick in at this stage.
>>
>> Maurizio
>>> Thank you,
>>> Anna
>>>
>>
>>
>>
>
> !DSPAM:35,54ddfbcc63031804284693!
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150213/5b473034/attachment-0001.html>
More information about the compiler-dev
mailing list