wrong target (this) in super default method invocation from a lambda
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Tue Aug 28 06:18:38 PDT 2012
This example works ok in the latest bits - note that, since 292
translation is enabled by default now, the problem of accessing super
from a class definition that is different from the one implementing the
interface doesn't exist anymore, as lambdas are translated as methods of
the class defining them (from which a super call is allowed).g
I will push shortly a patch that will bring the compiler in sync with
the latest EDR - the compiler is currently allowing super access from
classes nested inside an interface with default methods. The compiler
currently resolves I.super.m() using a comb lookup and returning the
innermost enclosing class that implements I (for which m() is a valid
default). This means that in the following case:
interface I {
void m() default { }
}
class Outer implements I {
void m() { new I() { void m() { I.super.m(); } } }
}
We have two choices:
*) I.m(), passing the anonymous I$1 as enclosing instance
*) I.m(), passing the enclosing 'this' as enclosing instance
Because of the comb lookup, the compiler is always selecting the first
choice. As discussed, this problem is going away: because of the
restriction imposed by the language the second choice will be illegal,
which means there's only one legal semantics for I.super.m() in the
above code.
Maurizio
Maurizio
On 28/08/12 09:28, Peter Levart wrote:
> The following code:
>
> package defaulttest;
>
> public class Outer implements K {
> @Override
> public void m() {
>
> Runnable r = () -> { K.super.m(); };
> r.run();
>
> K.super.m();
> }
>
> public static void main(String[] args)
> {
> new Outer().m();
> }
> }
>
>
> in combination with the below interface K also produces the following result:
>
> K.m() this: defaulttest.Outer$1 at 712801c5; Runnable: YES; Outer: NO
> K.m() this: defaulttest.Outer at 798c668c; Runnable: NO; Outer: YES
>
>
> Lambdas are (almost) fully transparent, so this should compile (as opposed to
> anonymous inner classes where it is not supported at the moment).
>
>
> Regards, Peter
>
> On Monday, August 27, 2012 04:30:48 PM Peter Levart wrote:
>> While experimenting with current syntax for calling super default methods I
>> think I found a bug in b50 compiler. The following example:
>>
>> package defaulttest;
>>
>> public interface K {
>> void m() default {
>> System.out.println(
>> "K.m() this: " + this +
>> "; Runnable: " + (this instanceof Runnable ? "YES" : "NO") +
>> "; Outer: " + (this instanceof Outer ? "YES" : "NO")
>> );
>> }
>> }
>>
>>
>> package defaulttest;
>>
>> public class Outer implements K {
>> @Override
>> public void m() {
>>
>> new Runnable() {
>> @Override
>> public void run() {
>> K.super.m();
>> }
>> }.run();
>>
>> K.super.m();
>> }
>>
>> public static void main(String[] args)
>> {
>> new Outer().m();
>> }
>> }
>>
>>
>> ...prints the following:
>>
>> K.m() this: defaulttest.Outer$1 at 798c668c; Runnable: YES; Outer: NO
>> K.m() this: defaulttest.Outer at 70a0afab; Runnable: NO; Outer: YES
>>
>>
>> The first line indicates that the K.m() default method is invoked, but with
>> the wrong target (this) being the instance of the inner Runnable instead of
>> Outer.this ...
>>
>>
>> Regards, Peter
More information about the lambda-dev
mailing list