wrong target (this) in super default method invocation from a lambda
Peter Levart
peter.levart at marand.si
Wed Aug 29 01:06:06 PDT 2012
Hello Maurizio,
I can confirm that the latest build from lambda hg repo (as of 30 minutes ago) works correctly now for inner classes. If the inner class implements the interface it takes the inner class instance as a target for the super method, if it does not then it produces a compile time error although the outer instance implements the interface:
/home/peter/work/local/tests/src/defaulttest/Outer.java
Error:Error:line (12)error: not an enclosing class: K
Maybe just the message should read something more like: "not an enclosing class or directly implemented interface: K"
But the following code:
public class Outer implements K {
@Override
public void m() {
Runnable r = () -> { K.super.m(); };
r.run();
}
}
still produces compiler internal error:
Information:An exception has occurred in the compiler (1.8.0-internal). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you.
Information:java.lang.NullPointerException
Information: at com.sun.tools.javac.jvm.Code.emitop0(Code.java:540)
Information: at com.sun.tools.javac.jvm.Items$SelfItem.load(Items.java:371)
Information: at com.sun.tools.javac.jvm.Gen.visitSelect(Gen.java:2169)
Information: at com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:1810)
Information: at com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:832)
Information: at com.sun.tools.javac.jvm.Gen.visitApply(Gen.java:1685)
Information: at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1393)
Information: at com.sun.tools.javac.jvm.Gen.visitExec(Gen.java:1637)
Information: at com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1224)
Information: at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:679)
Information: at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:714)
Information: at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:700)
Information: at com.sun.tools.javac.jvm.Gen.genStats(Gen.java:751)
Information: at com.sun.tools.javac.jvm.Gen.visitBlock(Gen.java:1029)
Information: at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:837)
Information: at com.sun.tools.javac.jvm.Gen.genMethod(Gen.java:907)
Information: at com.sun.tools.javac.jvm.Gen.visitMethodDef(Gen.java:880)
Information: at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:721)
Information: at com.sun.tools.javac.jvm.Gen.genClass(Gen.java:2245)
Information: at com.sun.tools.javac.main.JavaCompiler.genCode(JavaCompiler.java:734)
Information: at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1478)
Information: at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1442)
Information: at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:892)
Information: at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:851)
Information: at com.sun.tools.javac.main.Main.compile(Main.java:441)
Information: at com.sun.tools.javac.main.Main.compile(Main.java:358)
Information: at com.sun.tools.javac.main.Main.compile(Main.java:347)
Information: at com.sun.tools.javac.main.Main.compile(Main.java:338)
Information: at com.sun.tools.javac.Main.compile(Main.java:76)
Information: at com.sun.tools.javac.Main.main(Main.java:61)
Information: at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Information: at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
Information: at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Information: at java.lang.reflect.Method.invoke(Method.java:474)
Information: at com.intellij.rt.compiler.JavacRunner.main(JavacRunner.java:71)
Information:Compilation completed with 1 error and 0 warnings
Information:1 error
Information:0 warnings
Error:Compiler internal error. Process terminated with exit code 4
Regards, Peter
On Tuesday, August 28, 2012 02:18:38 PM Maurizio Cimadamore wrote:
> 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