Community
Participate
Working Groups
BETA_JAVA8: ----------- The following program compiles with ECJ, but fails to compile with 8b115. It appears ECJ behavior is incorrect. // -- interface I { int run(int s1, int s2); } class X { static int f = ((I) (int x5, int x2) -> x1).run(10, 20); static int x1 = 2; }
Another example, which compiles with ECJ, but not with 8b115: ---------------------------------------------- package test.inline; interface I { I run(int s1); } class X { public static final I fi = x -> fi; } ---------------------------------------------
Srikanth, I think this needs to be taken to the 335 EG. JLS7 8.3.2.3 "Restrictions on the use of Fields during Initialization" says as point 4: "C is the innermost class or interface enclosing the usage". This should be expanded to include lambda bodies, e.g.: "C is the innermost class or interface enclosing the usage, or the usage occurs inside a lambda expression that occurs inside C". The informative text later in that section confirms this intention: "The restrictions above are designed to catch, at compile time, circular or otherwise malformed initializations." In case of lambda bodies, self-references don't cause malformed initializations. Example that shows that javac only disallows unqualified access as per 8.3.2.3: public class C { // OK: Runnable qi= () -> executeAndRepost(this.qi); static Runnable qs= () -> executeAndRepost(C.qs); // javac 1.8.0-ea-b115 says: error: self-reference in initializer Runnable i= () -> executeAndRepost(i); static Runnable s= () -> executeAndRepost(s); static void executeAndRepost(Runnable r) { } }
http://mail.openjdk.java.net/pipermail/lambda-spec-observers/2013-December/000588.html
Updated the spec request: http://mail.openjdk.java.net/pipermail/lambda-spec-observers/2013-December/000623.html The problem is actually not only about self-references from the lambda body of a field initializer, but about any forward reference that is forbidden by JLS7 8.3.2.3. A better example: ---------- public class D { int v1 = value; // Error for 8.3.2.3 (good). int v2 = D.this.value; // No simple name -> no error (good). IntSupplier s1 = () -> value; // Why error? IntSupplier s2 = new IntSupplier() { @Override public int getAsInt() { return value; // No error (good). } }; int value = 42; } ---------- There's absolutely no problem with the reference in s1's initializer. The only problem is that 8.3.2.3 needs to be updated to make lambda bodies behave the same as nested class bodies. REQUEST: ======== 8.3.2.3 should get a fifth point: "- The usage is not in a lambda expression body that occurs inside c." The next sentence could also be clarified to: "It is a compile-time error if any of the five requirements above are not met for such a forward reference." ======== FWIW, this still excludes the forward reference to "VALUE" here: public static final IntConsumer c = (@A(VALUE) int x) -> {}; public static final int VALUE = 42;
The plan is to conform to the present spec and reference compiler behavior and react at the right time to any changes as they happen.
Fix and test released here: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=cc95db68297f07027a83fc8b08b9b05722eceebc