提交 52ef9bf4 编写于 作者: E emc

8021339: Compile-time error during casting array to intersection

Summary: Add ability to have arrays in intersection types.
Reviewed-by: jjg, vromero
上级 591bad91
...@@ -244,7 +244,7 @@ public class Types { ...@@ -244,7 +244,7 @@ public class Types {
public Type visitClassType(ClassType t, Symbol sym) { public Type visitClassType(ClassType t, Symbol sym) {
if (t.tsym == sym) if (t.tsym == sym)
return t; return t;
Type base = asSuper(sym.type, t.tsym); Type base = asSuper(sym.type, t);
if (base == null) if (base == null)
return null; return null;
ListBuffer<Type> from = new ListBuffer<Type>(); ListBuffer<Type> from = new ListBuffer<Type>();
...@@ -687,7 +687,7 @@ public class Types { ...@@ -687,7 +687,7 @@ public class Types {
(t.flags() & SYNTHETIC) == 0; (t.flags() & SYNTHETIC) == 0;
} }
}; };
private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) { private boolean pendingBridges(ClassSymbol origin, TypeSymbol sym) {
//a symbol will be completed from a classfile if (a) symbol has //a symbol will be completed from a classfile if (a) symbol has
//an associated file object with CLASS kind and (b) the symbol has //an associated file object with CLASS kind and (b) the symbol has
//not been entered //not been entered
...@@ -696,11 +696,11 @@ public class Types { ...@@ -696,11 +696,11 @@ public class Types {
enter.getEnv(origin) == null) { enter.getEnv(origin) == null) {
return false; return false;
} }
if (origin == s) { if (origin == sym) {
return true; return true;
} }
for (Type t : interfaces(origin.type)) { for (Type t : interfaces(origin.type)) {
if (pendingBridges((ClassSymbol)t.tsym, s)) { if (pendingBridges((ClassSymbol)t.tsym, sym)) {
return true; return true;
} }
} }
...@@ -761,7 +761,7 @@ public class Types { ...@@ -761,7 +761,7 @@ public class Types {
} else if (t.hasTag(TYPEVAR)) { } else if (t.hasTag(TYPEVAR)) {
return isSubtypeUnchecked(t.getUpperBound(), s, warn); return isSubtypeUnchecked(t.getUpperBound(), s, warn);
} else if (!s.isRaw()) { } else if (!s.isRaw()) {
Type t2 = asSuper(t, s.tsym); Type t2 = asSuper(t, s);
if (t2 != null && t2.isRaw()) { if (t2 != null && t2.isRaw()) {
if (isReifiable(s)) { if (isReifiable(s)) {
warn.silentWarn(LintCategory.UNCHECKED); warn.silentWarn(LintCategory.UNCHECKED);
...@@ -914,7 +914,7 @@ public class Types { ...@@ -914,7 +914,7 @@ public class Types {
@Override @Override
public Boolean visitClassType(ClassType t, Type s) { public Boolean visitClassType(ClassType t, Type s) {
Type sup = asSuper(t, s.tsym); Type sup = asSuper(t, s);
return sup != null return sup != null
&& sup.tsym == s.tsym && sup.tsym == s.tsym
// You're not allowed to write // You're not allowed to write
...@@ -1935,30 +1935,42 @@ public class Types { ...@@ -1935,30 +1935,42 @@ public class Types {
* @param t a type * @param t a type
* @param sym a symbol * @param sym a symbol
*/ */
public Type asSuper(Type t, Symbol sym) { public Type asSuper(Type t, Symbol s) {
return asSuper.visit(t, sym); return asSuper(t, s.type);
}
public Type asSuper(Type t, Type s) {
return asSuper.visit(t, s);
} }
// where // where
private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() { private SimpleVisitor<Type,Type> asSuper = new SimpleVisitor<Type,Type>() {
public Type visitType(Type t, Symbol sym) { public Type visitType(Type t, Type s) {
return null; return null;
} }
@Override @Override
public Type visitClassType(ClassType t, Symbol sym) { public Type visitClassType(ClassType t, Type s) {
if (t.tsym == sym) if (t.tsym == s.tsym)
return t; return t;
Type st = supertype(t); Type st = supertype(t);
if (st.hasTag(CLASS) || st.hasTag(TYPEVAR) || st.hasTag(ERROR)) {
Type x = asSuper(st, sym); switch(st.getTag()) {
default: break;
case CLASS:
case ARRAY:
case TYPEVAR:
case ERROR: {
Type x = asSuper(st, s);
if (x != null) if (x != null)
return x; return x;
} break;
} }
if ((sym.flags() & INTERFACE) != 0) {
if ((s.tsym.flags() & INTERFACE) != 0) {
for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) { for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
Type x = asSuper(l.head, sym); Type x = asSuper(l.head, s);
if (x != null) if (x != null)
return x; return x;
} }
...@@ -1967,22 +1979,20 @@ public class Types { ...@@ -1967,22 +1979,20 @@ public class Types {
} }
@Override @Override
public Type visitArrayType(ArrayType t, Symbol sym) { public Type visitArrayType(ArrayType t, Type s) {
return isSubtype(t, sym.type) ? sym.type : null; return isSubtype(t, s) ? s : null;
} }
@Override @Override
public Type visitTypeVar(TypeVar t, Symbol sym) { public Type visitTypeVar(TypeVar t, Type s) {
if (t.tsym == sym) if (t.tsym == s.tsym)
return t; return t;
else else
return asSuper(t.bound, sym); return asSuper(t.bound, s);
} }
@Override @Override
public Type visitErrorType(ErrorType t, Symbol sym) { public Type visitErrorType(ErrorType t, Type s) { return t; }
return t;
}
}; };
/** /**
...@@ -3563,9 +3573,9 @@ public class Types { ...@@ -3563,9 +3573,9 @@ public class Types {
//step 3 - for each element G in MEC, compute lci(Inv(G)) //step 3 - for each element G in MEC, compute lci(Inv(G))
List<Type> candidates = List.nil(); List<Type> candidates = List.nil();
for (Type erasedSupertype : mec) { for (Type erasedSupertype : mec) {
List<Type> lci = List.of(asSuper(ts.head, erasedSupertype.tsym)); List<Type> lci = List.of(asSuper(ts.head, erasedSupertype));
for (Type t : ts) { for (Type t : ts) {
lci = intersect(lci, List.of(asSuper(t, erasedSupertype.tsym))); lci = intersect(lci, List.of(asSuper(t, erasedSupertype)));
} }
candidates = candidates.appendList(lci); candidates = candidates.appendList(lci);
} }
...@@ -3985,7 +3995,7 @@ public class Types { ...@@ -3985,7 +3995,7 @@ public class Types {
// The arguments to the supers could be unified here to // The arguments to the supers could be unified here to
// get a more accurate analysis // get a more accurate analysis
while (commonSupers.nonEmpty()) { while (commonSupers.nonEmpty()) {
Type t1 = asSuper(from, commonSupers.head.tsym); Type t1 = asSuper(from, commonSupers.head);
Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym); Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym);
if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments())) if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
return false; return false;
...@@ -4016,7 +4026,7 @@ public class Types { ...@@ -4016,7 +4026,7 @@ public class Types {
from = target; from = target;
} }
Assert.check((from.tsym.flags() & FINAL) != 0); Assert.check((from.tsym.flags() & FINAL) != 0);
Type t1 = asSuper(from, to.tsym); Type t1 = asSuper(from, to);
if (t1 == null) return false; if (t1 == null) return false;
Type t2 = to; Type t2 = to;
if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments())) if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
......
...@@ -58,6 +58,7 @@ import static com.sun.tools.javac.code.Kinds.*; ...@@ -58,6 +58,7 @@ import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.Kinds.ERRONEOUS; import static com.sun.tools.javac.code.Kinds.ERRONEOUS;
import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.code.TypeTag.WILDCARD; import static com.sun.tools.javac.code.TypeTag.WILDCARD;
import static com.sun.tools.javac.code.TypeTag.ARRAY;
import static com.sun.tools.javac.tree.JCTree.Tag.*; import static com.sun.tools.javac.tree.JCTree.Tag.*;
/** This is the main context-dependent analysis phase in GJC. It /** This is the main context-dependent analysis phase in GJC. It
...@@ -797,28 +798,32 @@ public class Attr extends JCTree.Visitor { ...@@ -797,28 +798,32 @@ public class Attr extends JCTree.Visitor {
JCTree tree, JCTree tree,
Env<AttrContext> env, Env<AttrContext> env,
boolean classExpected, boolean classExpected,
boolean interfaceExpected, boolean interfaceOrArrayExpected,
boolean checkExtensible) { boolean checkExtensible) {
if (t.isErroneous()) if (t.isErroneous())
return t; return t;
if (t.hasTag(TYPEVAR) && !classExpected && !interfaceExpected) { if (t.hasTag(TYPEVAR) && !classExpected && !interfaceOrArrayExpected) {
// check that type variable is already visible // check that type variable is already visible
if (t.getUpperBound() == null) { if (t.getUpperBound() == null) {
log.error(tree.pos(), "illegal.forward.ref"); log.error(tree.pos(), "illegal.forward.ref");
return types.createErrorType(t); return types.createErrorType(t);
} }
} else { } else if (classExpected) {
t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics); t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics);
} else {
t = chk.checkClassOrArrayType(tree.pos(), t,
checkExtensible|!allowGenerics);
} }
if (interfaceExpected && (t.tsym.flags() & INTERFACE) == 0) { if (interfaceOrArrayExpected &&
!(t.tsym.isInterface() || t.getTag() == ARRAY)) {
log.error(tree.pos(), "intf.expected.here"); log.error(tree.pos(), "intf.expected.here");
// return errType is necessary since otherwise there might // return errType is necessary since otherwise there might
// be undetected cycles which cause attribution to loop // be undetected cycles which cause attribution to loop
return types.createErrorType(t); return types.createErrorType(t);
} else if (checkExtensible && } else if (checkExtensible &&
classExpected && classExpected &&
(t.tsym.flags() & INTERFACE) != 0) { t.tsym.isInterface()) {
log.error(tree.pos(), "no.intf.expected.here"); log.error(tree.pos(), "no.intf.expected.here");
return types.createErrorType(t); return types.createErrorType(t);
} }
if (checkExtensible && if (checkExtensible &&
...@@ -829,6 +834,12 @@ public class Attr extends JCTree.Visitor { ...@@ -829,6 +834,12 @@ public class Attr extends JCTree.Visitor {
chk.checkNonCyclic(tree.pos(), t); chk.checkNonCyclic(tree.pos(), t);
return t; return t;
} }
//where
private Object asTypeParam(Type t) {
return (t.hasTag(TYPEVAR))
? diags.fragment("type.parameter", t)
: t;
}
Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) { Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) {
Assert.check((env.enclClass.sym.flags() & ENUM) != 0); Assert.check((env.enclClass.sym.flags() & ENUM) != 0);
......
...@@ -706,6 +706,37 @@ public class Check { ...@@ -706,6 +706,37 @@ public class Check {
return t; return t;
} }
// Analog of checkClassType that calls checkClassOrArrayType instead
Type checkClassOrArrayType(DiagnosticPosition pos,
Type t, boolean noBounds) {
t = checkClassOrArrayType(pos, t);
if (noBounds && t.isParameterized()) {
List<Type> args = t.getTypeArguments();
while (args.nonEmpty()) {
if (args.head.hasTag(WILDCARD))
return typeTagError(pos,
diags.fragment("type.req.exact"),
args.head);
args = args.tail;
}
}
return t;
}
/** Check that type is a reifiable class, interface or array type.
* @param pos Position to be used for error reporting.
* @param t The type to be checked.
*/
Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) {
t = checkClassOrArrayType(pos, t);
if (!t.isErroneous() && !types.isReifiable(t)) {
log.error(pos, "illegal.generic.type.for.instof");
return types.createErrorType(t);
} else {
return t;
}
}
/** Check that type is a reference type, i.e. a class, interface or array type /** Check that type is a reference type, i.e. a class, interface or array type
* or a type variable. * or a type variable.
* @param pos Position to be used for error reporting. * @param pos Position to be used for error reporting.
...@@ -2210,6 +2241,9 @@ public class Check { ...@@ -2210,6 +2241,9 @@ public class Check {
seen = seen.prepend(tv); seen = seen.prepend(tv);
for (Type b : types.getBounds(tv)) for (Type b : types.getBounds(tv))
checkNonCyclic1(pos, b, seen); checkNonCyclic1(pos, b, seen);
} else if (t.hasTag(ARRAY)) {
final ArrayType at = (ArrayType)t.unannotatedType();
checkNonCyclic1(pos, at.elemtype, seen);
} }
} }
......
/*
* Copyright (c) 2013, 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 8021339
* @summary Allow arrays in intersection types
* @compile ArraysInIntersections.java
*/
import java.io.Serializable;
public class ArraysInIntersections<T extends Serializable & Integer[]> {
public <S extends Serializable & Integer[]> Object m() {
return (Serializable & Integer[]) new Integer[1];
}
}
/*
* Copyright (c) 2013, 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 8021339
* @summary Allow arrays in intersection types
* @compile -doe -XDrawDiagnostics InferArraysInIntersections.java
*/
import java.util.*;
class InferArraysInIntersections {
<T> T m(List<? super T> t) { return null; }
void test(List<char[]> lc) {
Runnable r = m(lc); //inference fails here
}
}
T6680106.java:11:25: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) T6680106.java:11:14: compiler.err.cyclic.inheritance: T
T6680106.java:12:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) T6680106.java:12:14: compiler.err.cyclic.inheritance: T
T6680106.java:12:40: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) T6680106.java:13:14: compiler.err.cyclic.inheritance: T
T6680106.java:13:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) T6680106.java:14:14: compiler.err.cyclic.inheritance: T
T6680106.java:13:40: compiler.err.type.found.req: U[], (compiler.misc.type.req.class) T6680106.java:15:14: compiler.err.cyclic.inheritance: T
T6680106.java:13:55: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) T6680106.java:16:14: compiler.err.cyclic.inheritance: T
T6680106.java:14:30: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) 6 errors
T6680106.java:15:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
T6680106.java:15:50: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
T6680106.java:16:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
T6680106.java:16:50: compiler.err.type.found.req: U[], (compiler.misc.type.req.class)
T6680106.java:16:70: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
12 errors
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册