Wed, 10 Nov 2010 12:37:25 +0000
6996914: Diamond inference: problem when accessing protected constructor
Summary: special resolution scheme for diamond inference needs to open up protected constructors in anon inner class creation
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Nov 09 17:49:24 2010 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Nov 10 12:37:25 2010 +0000 1.3 @@ -1552,7 +1552,7 @@ 1.4 // Attribute clazz expression and store 1.5 // symbol + type back into the attributed tree. 1.6 Type clazztype = attribType(clazz, env); 1.7 - Pair<Scope,Scope> mapping = getSyntheticScopeMapping(clazztype); 1.8 + Pair<Scope,Scope> mapping = getSyntheticScopeMapping(clazztype, cdef != null); 1.9 if (!TreeInfo.isDiamond(tree)) { 1.10 clazztype = chk.checkClassType( 1.11 tree.clazz.pos(), clazztype, true); 1.12 @@ -1849,7 +1849,7 @@ 1.13 * inference. The inferred return type of the synthetic constructor IS 1.14 * the inferred type for the diamond operator. 1.15 */ 1.16 - private Pair<Scope, Scope> getSyntheticScopeMapping(Type ctype) { 1.17 + private Pair<Scope, Scope> getSyntheticScopeMapping(Type ctype, boolean overrideProtectedAccess) { 1.18 if (ctype.tag != CLASS) { 1.19 return erroneousMapping; 1.20 } 1.21 @@ -1860,6 +1860,12 @@ 1.22 e.scope != null; 1.23 e = e.next()) { 1.24 MethodSymbol newConstr = (MethodSymbol) e.sym.clone(ctype.tsym); 1.25 + if (overrideProtectedAccess && (newConstr.flags() & PROTECTED) != 0) { 1.26 + //make protected constructor public (this is required for 1.27 + //anonymous inner class creation expressions using diamond) 1.28 + newConstr.flags_field |= PUBLIC; 1.29 + newConstr.flags_field &= ~PROTECTED; 1.30 + } 1.31 newConstr.name = names.init; 1.32 List<Type> oldTypeargs = List.nil(); 1.33 if (newConstr.type.tag == FORALL) {
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javac/generics/diamond/6996914/T6996914a.java Wed Nov 10 12:37:25 2010 +0000 2.3 @@ -0,0 +1,171 @@ 2.4 +/* 2.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +/* 2.28 + * @test 2.29 + * @bug 6996914 2.30 + * @summary Diamond inference: problem when accessing protected constructor 2.31 + * @run main T6996914a 2.32 + */ 2.33 + 2.34 +import com.sun.source.util.JavacTask; 2.35 +import java.net.URI; 2.36 +import java.util.Arrays; 2.37 +import javax.tools.Diagnostic; 2.38 +import javax.tools.DiagnosticListener; 2.39 +import javax.tools.JavaCompiler; 2.40 +import javax.tools.JavaFileObject; 2.41 +import javax.tools.SimpleJavaFileObject; 2.42 +import javax.tools.ToolProvider; 2.43 + 2.44 +public class T6996914a { 2.45 + 2.46 + enum PackageKind { 2.47 + DEFAULT("", ""), 2.48 + A("package a;", "import a.*;"); 2.49 + 2.50 + String pkgDecl; 2.51 + String importDecl; 2.52 + 2.53 + PackageKind(String pkgDecl, String importDecl) { 2.54 + this.pkgDecl = pkgDecl; 2.55 + this.importDecl = importDecl; 2.56 + } 2.57 + } 2.58 + 2.59 + enum DiamondKind { 2.60 + STANDARD("new Foo<>();"), 2.61 + ANON("new Foo<>() {};"); 2.62 + 2.63 + String expr; 2.64 + 2.65 + DiamondKind(String expr) { 2.66 + this.expr = expr; 2.67 + } 2.68 + } 2.69 + 2.70 + enum ConstructorKind { 2.71 + PACKAGE(""), 2.72 + PROTECTED("protected"), 2.73 + PRIVATE("private"), 2.74 + PUBLIC("public"); 2.75 + 2.76 + String mod; 2.77 + 2.78 + ConstructorKind(String mod) { 2.79 + this.mod = mod; 2.80 + } 2.81 + } 2.82 + 2.83 + static class FooClass extends SimpleJavaFileObject { 2.84 + 2.85 + final static String sourceStub = 2.86 + "#P\n" + 2.87 + "public class Foo<X> {\n" + 2.88 + " #M Foo() {}\n" + 2.89 + "}\n"; 2.90 + 2.91 + String source; 2.92 + 2.93 + public FooClass(PackageKind pk, ConstructorKind ck) { 2.94 + super(URI.create("myfo:/" + (pk != PackageKind.DEFAULT ? "a/Foo.java" : "Foo.java")), 2.95 + JavaFileObject.Kind.SOURCE); 2.96 + source = sourceStub.replace("#P", pk.pkgDecl).replace("#M", ck.mod); 2.97 + } 2.98 + 2.99 + @Override 2.100 + public CharSequence getCharContent(boolean ignoreEncodingErrors) { 2.101 + return source; 2.102 + } 2.103 + } 2.104 + 2.105 + static class ClientClass extends SimpleJavaFileObject { 2.106 + 2.107 + final static String sourceStub = 2.108 + "#I\n" + 2.109 + "class Test {\n" + 2.110 + " Foo<String> fs = #D\n" + 2.111 + "}\n"; 2.112 + 2.113 + String source; 2.114 + 2.115 + public ClientClass(PackageKind pk, DiamondKind dk) { 2.116 + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 2.117 + source = sourceStub.replace("#I", pk.importDecl).replace("#D", dk.expr); 2.118 + } 2.119 + 2.120 + @Override 2.121 + public CharSequence getCharContent(boolean ignoreEncodingErrors) { 2.122 + return source; 2.123 + } 2.124 + } 2.125 + 2.126 + public static void main(String... args) throws Exception { 2.127 + for (PackageKind pk : PackageKind.values()) { 2.128 + for (ConstructorKind ck : ConstructorKind.values()) { 2.129 + for (DiamondKind dk : DiamondKind.values()) { 2.130 + compileAndCheck(pk, ck, dk); 2.131 + } 2.132 + } 2.133 + } 2.134 + } 2.135 + 2.136 + static void compileAndCheck(PackageKind pk, ConstructorKind ck, DiamondKind dk) throws Exception { 2.137 + FooClass foo = new FooClass(pk, ck); 2.138 + ClientClass client = new ClientClass(pk, dk); 2.139 + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 2.140 + ErrorListener el = new ErrorListener(); 2.141 + JavacTask ct = (JavacTask)tool.getTask(null, null, el, 2.142 + null, null, Arrays.asList(foo, client)); 2.143 + ct.analyze(); 2.144 + if (el.errors > 0 == check(pk, ck, dk)) { 2.145 + String msg = el.errors > 0 ? 2.146 + "Error compiling files" : 2.147 + "No error when compiling files"; 2.148 + throw new AssertionError(msg + ": \n" + foo.source + "\n" + client.source); 2.149 + } 2.150 + } 2.151 + 2.152 + static boolean check(PackageKind pk, ConstructorKind ck, DiamondKind dk) { 2.153 + switch (pk) { 2.154 + case A: return ck == ConstructorKind.PUBLIC || 2.155 + (ck == ConstructorKind.PROTECTED && dk == DiamondKind.ANON); 2.156 + case DEFAULT: return ck != ConstructorKind.PRIVATE; 2.157 + default: throw new AssertionError("Unknown package kind"); 2.158 + } 2.159 + } 2.160 + 2.161 + /** 2.162 + * DiagnosticListener to count any errors that occur 2.163 + */ 2.164 + private static class ErrorListener implements DiagnosticListener<JavaFileObject> { 2.165 + 2.166 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 2.167 + switch (diagnostic.getKind()) { 2.168 + case ERROR: 2.169 + errors++; 2.170 + } 2.171 + } 2.172 + int errors; 2.173 + } 2.174 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/generics/diamond/6996914/T6996914b.java Wed Nov 10 12:37:25 2010 +0000 3.3 @@ -0,0 +1,39 @@ 3.4 +/* 3.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/* 3.28 + * @test 3.29 + * @bug 6996914 3.30 + * @summary Diamond inference: problem when accessing protected constructor 3.31 + * @compile T6996914b.java 3.32 + */ 3.33 + 3.34 +class Super<X,Y> { 3.35 + private Super(Integer i, Y y, X x) {} 3.36 + public Super(Number n, X x, Y y) {} 3.37 +} 3.38 + 3.39 +class Test { 3.40 + Super<String,Integer> ssi1 = new Super<>(1, "", 2); 3.41 + Super<String,Integer> ssi2 = new Super<>(1, "", 2) {}; 3.42 +}