提交 66c76689 编写于 作者: M mcimadamore

6732484: Bound error on wildcard code

Summary: Check.checkExtends should cope with captured type-variables
Reviewed-by: jjg
上级 54e6fa4c
......@@ -360,17 +360,6 @@ public class Type implements PrimitiveType {
public boolean isUnbound() { return false; }
public Type withTypeVar(Type t) { return this; }
public static List<Type> removeBounds(List<Type> ts) {
ListBuffer<Type> result = new ListBuffer<Type>();
for(;ts.nonEmpty(); ts = ts.tail) {
result.append(ts.head.removeBounds());
}
return result.toList();
}
public Type removeBounds() {
return this;
}
/** The underlying method type of this type.
*/
public MethodType asMethodType() { throw new AssertionError(); }
......@@ -489,10 +478,6 @@ public class Type implements PrimitiveType {
return new WildcardType(t, kind, tsym, bound);
}
public Type removeBounds() {
return isUnbound() ? this : type;
}
public Type getExtendsBound() {
if (kind == EXTENDS)
return type;
......
......@@ -424,43 +424,43 @@ public class Check {
* @param bs The bound.
*/
private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) {
if (a.tag == TYPEVAR && ((TypeVar)a).isCaptured()) {
CapturedType ct = (CapturedType)a;
boolean ok;
if (ct.bound.isErroneous()) {//capture doesn't exist
ok = false;
}
else {
switch (ct.wildcard.kind) {
case EXTENDS:
ok = types.isCastable(bs.getUpperBound(),
types.upperBound(a),
Warner.noWarnings);
break;
case SUPER:
ok = !types.notSoftSubtype(types.lowerBound(a),
bs.getUpperBound());
break;
case UNBOUND:
ok = true;
break;
default:
throw new AssertionError("Invalid bound kind");
}
}
if (!ok)
log.error(pos, "not.within.bounds", a);
}
else {
a = types.upperBound(a);
for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) {
if (!types.isSubtype(a, l.head)) {
log.error(pos, "not.within.bounds", a);
return;
}
if (a.isUnbound()) {
return;
} else if (a.tag != WILDCARD) {
a = types.upperBound(a);
for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) {
if (!types.isSubtype(a, l.head)) {
log.error(pos, "not.within.bounds", a);
return;
}
}
} else if (a.isExtendsBound()) {
if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings))
log.error(pos, "not.within.bounds", a);
} else if (a.isSuperBound()) {
if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound()))
log.error(pos, "not.within.bounds", a);
}
}
/** Check that a type is within some bounds.
*
* Used in TypeApply to verify that, e.g., X in V<X> is a valid
* type argument.
* @param pos Position to be used for error reporting.
* @param a The type that should be bounded by bs.
* @param bs The bound.
*/
private void checkCapture(JCTypeApply tree) {
List<JCExpression> args = tree.getTypeArguments();
for (Type arg : types.capture(tree.type).getTypeArguments()) {
if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) {
log.error(args.head.pos, "not.within.bounds", args.head.type);
break;
}
args = args.tail;
}
}
}
/** Check that type is different from 'void'.
* @param pos Position to be used for error reporting.
......@@ -803,7 +803,7 @@ public class Check {
public void visitTypeApply(JCTypeApply tree) {
if (tree.type.tag == CLASS) {
List<Type> formals = tree.type.tsym.type.getTypeArguments();
List<Type> actuals = types.capture(tree.type).getTypeArguments();
List<Type> actuals = tree.type.getTypeArguments();
List<JCExpression> args = tree.arguments;
List<Type> forms = formals;
ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>();
......@@ -826,25 +826,29 @@ public class Check {
}
args = tree.arguments;
List<TypeVar> tvars = tvars_buf.toList();
while (args.nonEmpty() && tvars.nonEmpty()) {
List<Type> tvars_cap = types.substBounds(formals,
formals,
types.capture(tree.type).getTypeArguments());
while (args.nonEmpty() && tvars_cap.nonEmpty()) {
// Let the actual arguments know their bound
args.head.type.withTypeVar(tvars.head);
args.head.type.withTypeVar((TypeVar)tvars_cap.head);
args = args.tail;
tvars = tvars.tail;
tvars_cap = tvars_cap.tail;
}
args = tree.arguments;
tvars = tvars_buf.toList();
List<TypeVar> tvars = tvars_buf.toList();
while (args.nonEmpty() && tvars.nonEmpty()) {
checkExtends(args.head.pos(),
actuals.head,
args.head.type,
tvars.head);
args = args.tail;
tvars = tvars.tail;
actuals = actuals.tail;
}
checkCapture(tree);
// Check that this type is either fully parameterized, or
// not parameterized at all.
if (tree.type.getEnclosingType().isRaw())
......
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6732484
* @summary Bound error on wildcard code
* @author Maurizio Cimadamore
* @compile T6732484.java
*/
class T6732484 {
class A<T extends A<T>> {}
class B extends A<B> {}
A<? super B> f;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册