Tue, 01 Oct 2013 17:41:57 -0400
8021339: Compile-time error during casting array to intersection
Summary: Add ability to have arrays in intersection types.
Reviewed-by: jjg, vromero
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Tue Oct 01 17:03:31 2013 +0400 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Tue Oct 01 17:41:57 2013 -0400 1.3 @@ -244,7 +244,7 @@ 1.4 public Type visitClassType(ClassType t, Symbol sym) { 1.5 if (t.tsym == sym) 1.6 return t; 1.7 - Type base = asSuper(sym.type, t.tsym); 1.8 + Type base = asSuper(sym.type, t); 1.9 if (base == null) 1.10 return null; 1.11 ListBuffer<Type> from = new ListBuffer<Type>(); 1.12 @@ -687,7 +687,7 @@ 1.13 (t.flags() & SYNTHETIC) == 0; 1.14 } 1.15 }; 1.16 - private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) { 1.17 + private boolean pendingBridges(ClassSymbol origin, TypeSymbol sym) { 1.18 //a symbol will be completed from a classfile if (a) symbol has 1.19 //an associated file object with CLASS kind and (b) the symbol has 1.20 //not been entered 1.21 @@ -696,11 +696,11 @@ 1.22 enter.getEnv(origin) == null) { 1.23 return false; 1.24 } 1.25 - if (origin == s) { 1.26 + if (origin == sym) { 1.27 return true; 1.28 } 1.29 for (Type t : interfaces(origin.type)) { 1.30 - if (pendingBridges((ClassSymbol)t.tsym, s)) { 1.31 + if (pendingBridges((ClassSymbol)t.tsym, sym)) { 1.32 return true; 1.33 } 1.34 } 1.35 @@ -761,7 +761,7 @@ 1.36 } else if (t.hasTag(TYPEVAR)) { 1.37 return isSubtypeUnchecked(t.getUpperBound(), s, warn); 1.38 } else if (!s.isRaw()) { 1.39 - Type t2 = asSuper(t, s.tsym); 1.40 + Type t2 = asSuper(t, s); 1.41 if (t2 != null && t2.isRaw()) { 1.42 if (isReifiable(s)) { 1.43 warn.silentWarn(LintCategory.UNCHECKED); 1.44 @@ -914,7 +914,7 @@ 1.45 1.46 @Override 1.47 public Boolean visitClassType(ClassType t, Type s) { 1.48 - Type sup = asSuper(t, s.tsym); 1.49 + Type sup = asSuper(t, s); 1.50 return sup != null 1.51 && sup.tsym == s.tsym 1.52 // You're not allowed to write 1.53 @@ -1935,30 +1935,42 @@ 1.54 * @param t a type 1.55 * @param sym a symbol 1.56 */ 1.57 - public Type asSuper(Type t, Symbol sym) { 1.58 - return asSuper.visit(t, sym); 1.59 + public Type asSuper(Type t, Symbol s) { 1.60 + return asSuper(t, s.type); 1.61 + } 1.62 + 1.63 + public Type asSuper(Type t, Type s) { 1.64 + return asSuper.visit(t, s); 1.65 } 1.66 // where 1.67 - private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() { 1.68 - 1.69 - public Type visitType(Type t, Symbol sym) { 1.70 + private SimpleVisitor<Type,Type> asSuper = new SimpleVisitor<Type,Type>() { 1.71 + 1.72 + public Type visitType(Type t, Type s) { 1.73 return null; 1.74 } 1.75 1.76 @Override 1.77 - public Type visitClassType(ClassType t, Symbol sym) { 1.78 - if (t.tsym == sym) 1.79 + public Type visitClassType(ClassType t, Type s) { 1.80 + if (t.tsym == s.tsym) 1.81 return t; 1.82 1.83 Type st = supertype(t); 1.84 - if (st.hasTag(CLASS) || st.hasTag(TYPEVAR) || st.hasTag(ERROR)) { 1.85 - Type x = asSuper(st, sym); 1.86 + 1.87 + switch(st.getTag()) { 1.88 + default: break; 1.89 + case CLASS: 1.90 + case ARRAY: 1.91 + case TYPEVAR: 1.92 + case ERROR: { 1.93 + Type x = asSuper(st, s); 1.94 if (x != null) 1.95 return x; 1.96 + } break; 1.97 } 1.98 - if ((sym.flags() & INTERFACE) != 0) { 1.99 + 1.100 + if ((s.tsym.flags() & INTERFACE) != 0) { 1.101 for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) { 1.102 - Type x = asSuper(l.head, sym); 1.103 + Type x = asSuper(l.head, s); 1.104 if (x != null) 1.105 return x; 1.106 } 1.107 @@ -1967,22 +1979,20 @@ 1.108 } 1.109 1.110 @Override 1.111 - public Type visitArrayType(ArrayType t, Symbol sym) { 1.112 - return isSubtype(t, sym.type) ? sym.type : null; 1.113 + public Type visitArrayType(ArrayType t, Type s) { 1.114 + return isSubtype(t, s) ? s : null; 1.115 } 1.116 1.117 @Override 1.118 - public Type visitTypeVar(TypeVar t, Symbol sym) { 1.119 - if (t.tsym == sym) 1.120 + public Type visitTypeVar(TypeVar t, Type s) { 1.121 + if (t.tsym == s.tsym) 1.122 return t; 1.123 else 1.124 - return asSuper(t.bound, sym); 1.125 + return asSuper(t.bound, s); 1.126 } 1.127 1.128 @Override 1.129 - public Type visitErrorType(ErrorType t, Symbol sym) { 1.130 - return t; 1.131 - } 1.132 + public Type visitErrorType(ErrorType t, Type s) { return t; } 1.133 }; 1.134 1.135 /** 1.136 @@ -3563,9 +3573,9 @@ 1.137 //step 3 - for each element G in MEC, compute lci(Inv(G)) 1.138 List<Type> candidates = List.nil(); 1.139 for (Type erasedSupertype : mec) { 1.140 - List<Type> lci = List.of(asSuper(ts.head, erasedSupertype.tsym)); 1.141 + List<Type> lci = List.of(asSuper(ts.head, erasedSupertype)); 1.142 for (Type t : ts) { 1.143 - lci = intersect(lci, List.of(asSuper(t, erasedSupertype.tsym))); 1.144 + lci = intersect(lci, List.of(asSuper(t, erasedSupertype))); 1.145 } 1.146 candidates = candidates.appendList(lci); 1.147 } 1.148 @@ -3985,7 +3995,7 @@ 1.149 // The arguments to the supers could be unified here to 1.150 // get a more accurate analysis 1.151 while (commonSupers.nonEmpty()) { 1.152 - Type t1 = asSuper(from, commonSupers.head.tsym); 1.153 + Type t1 = asSuper(from, commonSupers.head); 1.154 Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym); 1.155 if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments())) 1.156 return false; 1.157 @@ -4016,7 +4026,7 @@ 1.158 from = target; 1.159 } 1.160 Assert.check((from.tsym.flags() & FINAL) != 0); 1.161 - Type t1 = asSuper(from, to.tsym); 1.162 + Type t1 = asSuper(from, to); 1.163 if (t1 == null) return false; 1.164 Type t2 = to; 1.165 if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Oct 01 17:03:31 2013 +0400 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Oct 01 17:41:57 2013 -0400 2.3 @@ -58,6 +58,7 @@ 2.4 import static com.sun.tools.javac.code.Kinds.ERRONEOUS; 2.5 import static com.sun.tools.javac.code.TypeTag.*; 2.6 import static com.sun.tools.javac.code.TypeTag.WILDCARD; 2.7 +import static com.sun.tools.javac.code.TypeTag.ARRAY; 2.8 import static com.sun.tools.javac.tree.JCTree.Tag.*; 2.9 2.10 /** This is the main context-dependent analysis phase in GJC. It 2.11 @@ -797,28 +798,32 @@ 2.12 JCTree tree, 2.13 Env<AttrContext> env, 2.14 boolean classExpected, 2.15 - boolean interfaceExpected, 2.16 + boolean interfaceOrArrayExpected, 2.17 boolean checkExtensible) { 2.18 if (t.isErroneous()) 2.19 return t; 2.20 - if (t.hasTag(TYPEVAR) && !classExpected && !interfaceExpected) { 2.21 + if (t.hasTag(TYPEVAR) && !classExpected && !interfaceOrArrayExpected) { 2.22 // check that type variable is already visible 2.23 if (t.getUpperBound() == null) { 2.24 log.error(tree.pos(), "illegal.forward.ref"); 2.25 return types.createErrorType(t); 2.26 } 2.27 + } else if (classExpected) { 2.28 + t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics); 2.29 } else { 2.30 - t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics); 2.31 + t = chk.checkClassOrArrayType(tree.pos(), t, 2.32 + checkExtensible|!allowGenerics); 2.33 } 2.34 - if (interfaceExpected && (t.tsym.flags() & INTERFACE) == 0) { 2.35 + if (interfaceOrArrayExpected && 2.36 + !(t.tsym.isInterface() || t.getTag() == ARRAY)) { 2.37 log.error(tree.pos(), "intf.expected.here"); 2.38 // return errType is necessary since otherwise there might 2.39 // be undetected cycles which cause attribution to loop 2.40 return types.createErrorType(t); 2.41 } else if (checkExtensible && 2.42 classExpected && 2.43 - (t.tsym.flags() & INTERFACE) != 0) { 2.44 - log.error(tree.pos(), "no.intf.expected.here"); 2.45 + t.tsym.isInterface()) { 2.46 + log.error(tree.pos(), "no.intf.expected.here"); 2.47 return types.createErrorType(t); 2.48 } 2.49 if (checkExtensible && 2.50 @@ -829,6 +834,12 @@ 2.51 chk.checkNonCyclic(tree.pos(), t); 2.52 return t; 2.53 } 2.54 + //where 2.55 + private Object asTypeParam(Type t) { 2.56 + return (t.hasTag(TYPEVAR)) 2.57 + ? diags.fragment("type.parameter", t) 2.58 + : t; 2.59 + } 2.60 2.61 Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) { 2.62 Assert.check((env.enclClass.sym.flags() & ENUM) != 0);
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Oct 01 17:03:31 2013 +0400 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Oct 01 17:41:57 2013 -0400 3.3 @@ -706,6 +706,37 @@ 3.4 return t; 3.5 } 3.6 3.7 + // Analog of checkClassType that calls checkClassOrArrayType instead 3.8 + Type checkClassOrArrayType(DiagnosticPosition pos, 3.9 + Type t, boolean noBounds) { 3.10 + t = checkClassOrArrayType(pos, t); 3.11 + if (noBounds && t.isParameterized()) { 3.12 + List<Type> args = t.getTypeArguments(); 3.13 + while (args.nonEmpty()) { 3.14 + if (args.head.hasTag(WILDCARD)) 3.15 + return typeTagError(pos, 3.16 + diags.fragment("type.req.exact"), 3.17 + args.head); 3.18 + args = args.tail; 3.19 + } 3.20 + } 3.21 + return t; 3.22 + } 3.23 + 3.24 + /** Check that type is a reifiable class, interface or array type. 3.25 + * @param pos Position to be used for error reporting. 3.26 + * @param t The type to be checked. 3.27 + */ 3.28 + Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { 3.29 + t = checkClassOrArrayType(pos, t); 3.30 + if (!t.isErroneous() && !types.isReifiable(t)) { 3.31 + log.error(pos, "illegal.generic.type.for.instof"); 3.32 + return types.createErrorType(t); 3.33 + } else { 3.34 + return t; 3.35 + } 3.36 + } 3.37 + 3.38 /** Check that type is a reference type, i.e. a class, interface or array type 3.39 * or a type variable. 3.40 * @param pos Position to be used for error reporting. 3.41 @@ -2210,6 +2241,9 @@ 3.42 seen = seen.prepend(tv); 3.43 for (Type b : types.getBounds(tv)) 3.44 checkNonCyclic1(pos, b, seen); 3.45 + } else if (t.hasTag(ARRAY)) { 3.46 + final ArrayType at = (ArrayType)t.unannotatedType(); 3.47 + checkNonCyclic1(pos, at.elemtype, seen); 3.48 } 3.49 } 3.50
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/tools/javac/ArraysInIntersections.java Tue Oct 01 17:41:57 2013 -0400 4.3 @@ -0,0 +1,39 @@ 4.4 +/* 4.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 +/* 4.28 + * @test 4.29 + * @bug 8021339 4.30 + * @summary Allow arrays in intersection types 4.31 + * @compile ArraysInIntersections.java 4.32 + */ 4.33 + 4.34 +import java.io.Serializable; 4.35 + 4.36 +public class ArraysInIntersections<T extends Serializable & Integer[]> { 4.37 + 4.38 + public <S extends Serializable & Integer[]> Object m() { 4.39 + return (Serializable & Integer[]) new Integer[1]; 4.40 + } 4.41 + 4.42 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/InferArraysInIntersections.java Tue Oct 01 17:41:57 2013 -0400 5.3 @@ -0,0 +1,38 @@ 5.4 +/* 5.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +/* 5.28 + * @test 5.29 + * @bug 8021339 5.30 + * @summary Allow arrays in intersection types 5.31 + * @compile -doe -XDrawDiagnostics InferArraysInIntersections.java 5.32 + */ 5.33 +import java.util.*; 5.34 + 5.35 +class InferArraysInIntersections { 5.36 + <T> T m(List<? super T> t) { return null; } 5.37 + 5.38 + void test(List<char[]> lc) { 5.39 + Runnable r = m(lc); //inference fails here 5.40 + } 5.41 +}
6.1 --- a/test/tools/javac/generics/typevars/6680106/T6680106.out Tue Oct 01 17:03:31 2013 +0400 6.2 +++ b/test/tools/javac/generics/typevars/6680106/T6680106.out Tue Oct 01 17:41:57 2013 -0400 6.3 @@ -1,13 +1,7 @@ 6.4 -T6680106.java:11:25: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) 6.5 -T6680106.java:12:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) 6.6 -T6680106.java:12:40: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) 6.7 -T6680106.java:13:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) 6.8 -T6680106.java:13:40: compiler.err.type.found.req: U[], (compiler.misc.type.req.class) 6.9 -T6680106.java:13:55: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) 6.10 -T6680106.java:14:30: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) 6.11 -T6680106.java:15:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) 6.12 -T6680106.java:15:50: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) 6.13 -T6680106.java:16:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) 6.14 -T6680106.java:16:50: compiler.err.type.found.req: U[], (compiler.misc.type.req.class) 6.15 -T6680106.java:16:70: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) 6.16 -12 errors 6.17 +T6680106.java:11:14: compiler.err.cyclic.inheritance: T 6.18 +T6680106.java:12:14: compiler.err.cyclic.inheritance: T 6.19 +T6680106.java:13:14: compiler.err.cyclic.inheritance: T 6.20 +T6680106.java:14:14: compiler.err.cyclic.inheritance: T 6.21 +T6680106.java:15:14: compiler.err.cyclic.inheritance: T 6.22 +T6680106.java:16:14: compiler.err.cyclic.inheritance: T 6.23 +6 errors