Experimental fix for capturing anonymous classes inside lambda (JDK-8229862)

B. Blaser bsrbnd at gmail.com
Tue Oct 20 18:46:29 UTC 2020


Hi,

JDK-8229862 reveals that capturing anonymous classes inside lambda
seem not to be properly implemented yet, although the opposite
currently works fine in JDK-16 (see [1] or [2], for example).

The following experimental fix (on jdk14u) searches for local
variables captured by anonymous classes inside lambda (in
LambdaToMethod) and translates them according to corresponding proxies
(in Lower).

What do you think (langtools:tier1 is OK)?

Thanks,
Bernard

[1] test/langtools/tools/javac/lambda/T8209407/VerifierErrorInnerPlusLambda.java
[2] test/langtools/tools/javac/lambda/methodReference/ProtectedInaccessibleMethodRefTest.java

diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
@@ -1380,9 +1380,18 @@
             super.visitIdent(tree);
         }

+        boolean inLambda = false;
+
         @Override
         public void visitLambda(JCLambda tree) {
-            analyzeLambda(tree, "lambda.stat");
+            boolean prevInLambda = inLambda;
+            try {
+                inLambda = true;
+                analyzeLambda(tree, "lambda.stat");
+            }
+            finally {
+                inLambda = prevInLambda;
+            }
         }

         private void analyzeLambda(JCLambda tree, JCExpression
methodReferenceReceiver) {
@@ -1430,6 +1439,16 @@

         @Override
         public void visitNewClass(JCNewClass tree) {
+            if (tree.def != null && inLambda) {
+                try {
+                    inLambda = false;
+                    visitClassDef(tree.def);
+                }
+                finally {
+                    inLambda = true;
+                }
+            }
+
             TypeSymbol def = tree.type.tsym;
             boolean inReferencedClass = currentlyInClass(def);
             boolean isLocal = def.isLocal();
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
@@ -2812,7 +2812,14 @@
         // If we have an anonymous class, create its flat version, rather
         // than the class or interface following new.
         if (tree.def != null) {
-            translate(tree.def);
+            Map<Symbol, Symbol> prevLambdaTranslationMap =
lambdaTranslationMap;
+            try {
+                lambdaTranslationMap = null;
+                translate(tree.def);
+            } finally {
+                lambdaTranslationMap = prevLambdaTranslationMap;
+            }
+
             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
             tree.def = null;
         } else {


More information about the compiler-dev mailing list