hg: lambda/lambda/langtools: 8008537: Missing method reference lookup error when unbound search finds a static method

Ali Ebrahimi ali.ebrahimi1781 at gmail.com
Fri Feb 22 04:40:28 PST 2013


Thanks maurizio,
This test shows that the new scheme sucks in resolving method references in
overloaded generic methods contexts. May be we need better scheme, no?

Best Regards,
Ali Ebrahimi

On Fri, Feb 22, 2013 at 3:10 PM, Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:

>  I think the test - or  the types in the test, to be more precise, might
> be misleading you. The goal of this test is to check provisional
> applicability of method references, a new applicability step described in
> the spec EDR. When method reference happens to be 'stuck' - that is, when
> its target type contains inference variables in the parameter types of the
> functional descriptor (as it happens to be the case here), the compiler
> revert to a much more brittle applicability scheme. It essentially uses the
> target type to perform an arity based match of the available methods. So,
> assuming the target type is:
>
> SAM<Z>
>
> where Z is an inference variable and SAM is declared as follows:
>
> interface SAM<X> {
>     m(X x)
> }
>
> If you have something like:
>
> Foo::g
>
> whose target is SAM<Z>, the compiler will:
>
> 1) Look at the target type
> 2) See that the method reference is stuck (parameter types of functional
> descriptor contain Z)
> 3) See if Foo has a method matching with a 'jolly' parameter list (*)
> [where * stands for any type]
> 4) If the above condition is satisfied, the method is deemed applicable.
> Most specific then follows, and, once a most specific method has been
> selected you will have a precise check with all the inference bells and
> whistles.
>
> Now, if Foo is a class that has two methods:
>
> g()
> g(String) //any type will do
>
> The arity-based lookup described in (3) will match both methods.
>
> This shows that, since the arity-based lookup is fuzzy (can match methods
> with different arities due to the bound/unbound lookup differences) - it is
> possible for two target types with different arities to both have a match.
> This _doesn't_ mean that the target type will make the method reference
> checkable - it merely means that the provisional applicability step is
> satisfied (which means the method featuring that particular target type as
> formal argument is applicable).
>
> It is possible that, even removing one of the ambiguous methods you still
> get a compiler error down the road, because when the compiler starts to do
> full type-checking of the method reference it realizes something is wrong.
>
> Now, one could argue that if a method reference cannot be type-checked
> against a formal, a method should never be deemed applicable; that's
> possible - and it's the way the compiler used to work (before the overload
> resolution rewrital which happened late last year). However, there are
> situations in which you can't tell as to whether a method would be
> applicable or not unless you look at the target type of the method call.
> And we wanted to preserve the invariant that the outcome of overload
> resolution was still expressible as a function between actual argument
> types and formal argument types. Hence the provisional applicability check
> and the fuzzy arity-based matching.
>
> Of course, all of this only takes place when a method reference is stuck -
> which can only happen if you are calling a generic method.
>
> Maurizio
>
>
>
>
>
> On 21/02/13 22:27, Ali Ebrahimi wrote:
>
> Hi again maurizio,
> if i comment u(Sam2) method then we have one answer u(Sam1), correct?
>
> in that case, we woud have u(Sam1<String>) or u(Sam1<TargetType60>)?
>
> I think in any case this is not correct.
>
> u(Sam1<String>)   => TargetType60 s2 = u(TargetType60::n1);
> method u returns String and not compatible with TargetType60.
>
> u(Sam1<TargetType60>) => we missed n1 String parameter and fail at runtime.
>
>
>
>     interface Sam1<X> {
>         void m(X x);
>     }
>
> void n1(String s) { }
>
> static <U> U u(Sam1<U> s) {    s.m((U)null)     return null; }
>
> static void testUnbound() {
>          TargetType60 s2 = u(TargetType60::n1);
> }
>
> main question: what is receiver of this method reff passed to u(Sam1)?
>
> Best Regards,
> Ali Ebrahimi
>
> On Fri, Feb 22, 2013 at 1:58 AM, Maurizio Cimadamore <
> maurizio.cimadamore at oracle.com> wrote:
>
>>  On 21/02/13 21:16, Ali Ebrahimi wrote:
>>
>> Hi maurizio,
>>
>> are you sure this is ambiguous? I don't think so. (u(Sam2)  is not only
>> answer?)
>>
>> TargetType60 s2 = u(TargetType60::n1); //ambiguous (u(Sam1), u(Sam2)
>> apply)
>>
>>  They both apply - turned out I've misread the spec - the fact that the
>> method is static/non-static should not affect outcome of method reference
>> resolution. So, if target type has parameters P1 ... Pn, we do two lookups:
>>
>> *) one (bound) with P1 ... Pn
>> *) one (unbound) with P2 ... Pn
>>
>> The first lookup will cause the match in u(Sam1), while the second lookup
>> will match u(Sam2). Hence the ambiguity.
>>
>> Maurizio
>>
>>
>>
>> Best Regards,
>> Ali Ebrahimi
>>
>> On Wed, Feb 20, 2013 at 11:49 PM, <maurizio.cimadamore at oracle.com> wrote:
>>
>>> Changeset: 66476d1c5e64
>>> Author:    mcimadamore
>>> Date:      2013-02-20 19:19 +0000
>>> URL:
>>> http://hg.openjdk.java.net/lambda/lambda/langtools/rev/66476d1c5e64
>>>
>>> 8008537: Missing method reference lookup error when unbound search finds
>>> a static method
>>>
>>> ! src/share/classes/com/sun/tools/javac/comp/Attr.java
>>> ! src/share/classes/com/sun/tools/javac/comp/Resolve.java
>>> ! src/share/classes/com/sun/tools/javac/resources/compiler.properties
>>> ! test/tools/javac/diags/examples.not-yet.txt
>>> ! test/tools/javac/diags/examples/NonStaticCantBeRefFragment.java
>>> ! test/tools/javac/lambda/MethodReference22.java
>>> ! test/tools/javac/lambda/MethodReference22.out
>>> ! test/tools/javac/lambda/MethodReference28.out
>>> ! test/tools/javac/lambda/MethodReference51.out
>>> ! test/tools/javac/lambda/TargetType60.java
>>> ! test/tools/javac/lambda/TargetType60.out
>>>
>>>
>>>
>>
>>
>
>


More information about the lambda-dev mailing list