8182401: Verification error for enclosing instance capture inside super constructor invocation
Reviewed-by: vromero
--- 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