8182401: Verification error for enclosing instance capture inside super constructor invocation
authorsadayapalam
Mon, 11 Dec 2017 06:58:14 +0530
changeset 48234 e7342e1becb4
parent 48233 dd5157f363ab
child 48235 8db54e2c453b
8182401: Verification error for enclosing instance capture inside super constructor invocation Reviewed-by: vromero
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
test/langtools/tools/javac/lambda/ImplicitEnclosingInstanceTest.java
test/langtools/tools/javac/lambda/InnerInstanceCreationTest.java
test/langtools/tools/javac/lambda/methodReference/ImplicitEnclosingInstanceTest.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Dec 08 15:30:53 2017 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Mon Dec 11 06:58:14 2017 +0530
@@ -510,6 +510,28 @@
         }
     }
 
+    /**
+     * Translate instance creation expressions with implicit enclosing instances
+     * @param tree
+     */
+    @Override
+    public void visitNewClass(JCNewClass tree) {
+        if (context == null || !analyzer.lambdaNewClassFilter(context, tree)) {
+            super.visitNewClass(tree);
+        } else {
+            int prevPos = make.pos;
+            try {
+                make.at(tree);
+
+                LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
+                tree = lambdaContext.translate(tree);
+                super.visitNewClass(tree);
+            } finally {
+                make.at(prevPos);
+            }
+        }
+    }
+
     @Override
     public void visitVarDef(JCVariableDecl tree) {
         LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context;
@@ -984,6 +1006,7 @@
                 //create the instance creation expression
                 //note that method reference syntax does not allow an explicit
                 //enclosing class (so the enclosing class is null)
+                // but this may need to be patched up later with the proxy for the outer this
                 JCNewClass newClass = make.NewClass(null,
                         List.nil(),
                         make.Type(tree.getQualifierExpression().type),
@@ -2129,6 +2152,21 @@
                 return null;
             }
 
+            /* Translate away naked new instance creation expressions with implicit enclosing instances,
+               anchoring them to synthetic parameters that stand proxy for the qualified outer this handle.
+            */
+            public JCNewClass translate(JCNewClass newClass) {
+                Assert.check(newClass.clazz.type.tsym.hasOuterInstance() && newClass.encl == null);
+                Map<Symbol, Symbol> m = translatedSymbols.get(LambdaSymbolKind.CAPTURED_OUTER_THIS);
+                final Type enclosingType = newClass.clazz.type.getEnclosingType();
+                if (m.containsKey(enclosingType.tsym)) {
+                      Symbol tSym = m.get(enclosingType.tsym);
+                      JCExpression encl = make.Ident(tSym).setType(enclosingType);
+                      newClass.encl = encl;
+                }
+                return newClass;
+            }
+
             /**
              * The translatedSym is not complete/accurate until the analysis is
              * finished.  Once the analysis is finished, the translatedSym is
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/ImplicitEnclosingInstanceTest.java	Mon Dec 11 06:58:14 2017 +0530
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8182401
+ * @summary Verification error for enclosing instance capture inside super constructor invocation
+ * @run main ImplicitEnclosingInstanceTest
+ */
+
+import java.util.function.Function;
+
+public class ImplicitEnclosingInstanceTest {
+
+    static String cookie = "deadbeef";
+
+    static Object f(Function<String, Object> f) {
+        return f.apply("feed");
+    }
+
+    class S {
+        S(Object s) {
+            cookie += "face";
+        }
+    }
+
+    class A {
+        A(String s) {
+            cookie = s;
+        }
+    }
+
+    class B extends S {
+        B() {
+            super(f(s->new A(s)));
+        }
+    }
+
+    public static void main(String[] args) {
+        new ImplicitEnclosingInstanceTest().new B();
+        if (!cookie.equals("feedface"))
+            throw new AssertionError("Incorrect cookie!");
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/InnerInstanceCreationTest.java	Mon Dec 11 06:58:14 2017 +0530
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8182401 8178444
+ * @summary Verification error for enclosing instance capture inside super constructor invocation
+ * @run main InnerInstanceCreationTest
+ */
+
+import java.util.function.Supplier;
+
+public class InnerInstanceCreationTest {
+
+    static String cookie = "";
+
+    public static void main(String[] args) {
+        new InnerInstanceCreationTest().new Producer();
+        new InnerInstanceCreationTest().new Producer(0);
+        new InnerInstanceCreationTest().new Producer("");
+        if (!cookie.equals("BlahBlahBlah"))
+            throw new AssertionError("Unexpected cookie");
+    }
+
+    class Inner {
+        Inner() {
+            cookie += "Blah";
+        }
+    }
+
+    class Producer {
+        Producer() {
+            this(Inner::new);
+        }
+        Producer(int x) {
+            this(() -> new Inner());
+        }
+        Producer(String s) {
+            this(() -> InnerInstanceCreationTest.this.new Inner());
+        }
+        Producer(Supplier<Object> supplier) {
+            supplier.get();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/methodReference/ImplicitEnclosingInstanceTest.java	Mon Dec 11 06:58:14 2017 +0530
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8182401
+ * @summary Verification error for enclosing instance capture inside super constructor invocation
+ * @run main ImplicitEnclosingInstanceTest
+ */
+
+
+import java.util.function.Function;
+
+public class ImplicitEnclosingInstanceTest {
+    static String cookie = "deadbeef";
+    static Object f(Function<String, Object> f) {
+        return f.apply("feed");
+    }
+
+    class S {
+        S(Object s) {
+            cookie += "face";
+        }
+    }
+
+    class A {
+        A(String s) {
+            cookie = s;
+        }
+    }
+
+    class B extends S {
+        B() {
+            super(f(A::new));
+        }
+    }
+
+    public static void main(String[] args) {
+        new ImplicitEnclosingInstanceTest().new B();
+        if (!cookie.equals("feedface"))
+            throw new AssertionError("Incorrect cookie!");
+    }
+}
\ No newline at end of file