Thu, 23 Oct 2008 17:59:16 +0100
6732484: Bound error on wildcard code
Summary: Check.checkExtends should cope with captured type-variables
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Type.java Mon Oct 20 13:42:45 2008 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Type.java Thu Oct 23 17:59:16 2008 +0100 1.3 @@ -360,17 +360,6 @@ 1.4 public boolean isUnbound() { return false; } 1.5 public Type withTypeVar(Type t) { return this; } 1.6 1.7 - public static List<Type> removeBounds(List<Type> ts) { 1.8 - ListBuffer<Type> result = new ListBuffer<Type>(); 1.9 - for(;ts.nonEmpty(); ts = ts.tail) { 1.10 - result.append(ts.head.removeBounds()); 1.11 - } 1.12 - return result.toList(); 1.13 - } 1.14 - public Type removeBounds() { 1.15 - return this; 1.16 - } 1.17 - 1.18 /** The underlying method type of this type. 1.19 */ 1.20 public MethodType asMethodType() { throw new AssertionError(); } 1.21 @@ -489,10 +478,6 @@ 1.22 return new WildcardType(t, kind, tsym, bound); 1.23 } 1.24 1.25 - public Type removeBounds() { 1.26 - return isUnbound() ? this : type; 1.27 - } 1.28 - 1.29 public Type getExtendsBound() { 1.30 if (kind == EXTENDS) 1.31 return type;
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Oct 20 13:42:45 2008 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Oct 23 17:59:16 2008 +0100 2.3 @@ -424,43 +424,43 @@ 2.4 * @param bs The bound. 2.5 */ 2.6 private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { 2.7 - if (a.tag == TYPEVAR && ((TypeVar)a).isCaptured()) { 2.8 - CapturedType ct = (CapturedType)a; 2.9 - boolean ok; 2.10 - if (ct.bound.isErroneous()) {//capture doesn't exist 2.11 - ok = false; 2.12 + if (a.isUnbound()) { 2.13 + return; 2.14 + } else if (a.tag != WILDCARD) { 2.15 + a = types.upperBound(a); 2.16 + for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { 2.17 + if (!types.isSubtype(a, l.head)) { 2.18 + log.error(pos, "not.within.bounds", a); 2.19 + return; 2.20 + } 2.21 + } 2.22 + } else if (a.isExtendsBound()) { 2.23 + if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings)) 2.24 + log.error(pos, "not.within.bounds", a); 2.25 + } else if (a.isSuperBound()) { 2.26 + if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound())) 2.27 + log.error(pos, "not.within.bounds", a); 2.28 + } 2.29 + } 2.30 + 2.31 + /** Check that a type is within some bounds. 2.32 + * 2.33 + * Used in TypeApply to verify that, e.g., X in V<X> is a valid 2.34 + * type argument. 2.35 + * @param pos Position to be used for error reporting. 2.36 + * @param a The type that should be bounded by bs. 2.37 + * @param bs The bound. 2.38 + */ 2.39 + private void checkCapture(JCTypeApply tree) { 2.40 + List<JCExpression> args = tree.getTypeArguments(); 2.41 + for (Type arg : types.capture(tree.type).getTypeArguments()) { 2.42 + if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) { 2.43 + log.error(args.head.pos, "not.within.bounds", args.head.type); 2.44 + break; 2.45 } 2.46 - else { 2.47 - switch (ct.wildcard.kind) { 2.48 - case EXTENDS: 2.49 - ok = types.isCastable(bs.getUpperBound(), 2.50 - types.upperBound(a), 2.51 - Warner.noWarnings); 2.52 - break; 2.53 - case SUPER: 2.54 - ok = !types.notSoftSubtype(types.lowerBound(a), 2.55 - bs.getUpperBound()); 2.56 - break; 2.57 - case UNBOUND: 2.58 - ok = true; 2.59 - break; 2.60 - default: 2.61 - throw new AssertionError("Invalid bound kind"); 2.62 - } 2.63 - } 2.64 - if (!ok) 2.65 - log.error(pos, "not.within.bounds", a); 2.66 + args = args.tail; 2.67 } 2.68 - else { 2.69 - a = types.upperBound(a); 2.70 - for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { 2.71 - if (!types.isSubtype(a, l.head)) { 2.72 - log.error(pos, "not.within.bounds", a); 2.73 - return; 2.74 - } 2.75 - } 2.76 - } 2.77 - } 2.78 + } 2.79 2.80 /** Check that type is different from 'void'. 2.81 * @param pos Position to be used for error reporting. 2.82 @@ -803,7 +803,7 @@ 2.83 public void visitTypeApply(JCTypeApply tree) { 2.84 if (tree.type.tag == CLASS) { 2.85 List<Type> formals = tree.type.tsym.type.getTypeArguments(); 2.86 - List<Type> actuals = types.capture(tree.type).getTypeArguments(); 2.87 + List<Type> actuals = tree.type.getTypeArguments(); 2.88 List<JCExpression> args = tree.arguments; 2.89 List<Type> forms = formals; 2.90 ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>(); 2.91 @@ -826,24 +826,28 @@ 2.92 } 2.93 2.94 args = tree.arguments; 2.95 + List<Type> tvars_cap = types.substBounds(formals, 2.96 + formals, 2.97 + types.capture(tree.type).getTypeArguments()); 2.98 + while (args.nonEmpty() && tvars_cap.nonEmpty()) { 2.99 + // Let the actual arguments know their bound 2.100 + args.head.type.withTypeVar((TypeVar)tvars_cap.head); 2.101 + args = args.tail; 2.102 + tvars_cap = tvars_cap.tail; 2.103 + } 2.104 + 2.105 + args = tree.arguments; 2.106 List<TypeVar> tvars = tvars_buf.toList(); 2.107 + 2.108 while (args.nonEmpty() && tvars.nonEmpty()) { 2.109 - // Let the actual arguments know their bound 2.110 - args.head.type.withTypeVar(tvars.head); 2.111 + checkExtends(args.head.pos(), 2.112 + args.head.type, 2.113 + tvars.head); 2.114 args = args.tail; 2.115 tvars = tvars.tail; 2.116 } 2.117 2.118 - args = tree.arguments; 2.119 - tvars = tvars_buf.toList(); 2.120 - while (args.nonEmpty() && tvars.nonEmpty()) { 2.121 - checkExtends(args.head.pos(), 2.122 - actuals.head, 2.123 - tvars.head); 2.124 - args = args.tail; 2.125 - tvars = tvars.tail; 2.126 - actuals = actuals.tail; 2.127 - } 2.128 + checkCapture(tree); 2.129 2.130 // Check that this type is either fully parameterized, or 2.131 // not parameterized at all.
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/generics/wildcards/T6732484.java Thu Oct 23 17:59:16 2008 +0100 3.3 @@ -0,0 +1,37 @@ 3.4 +/* 3.5 + * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 3.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 3.24 + * have any questions. 3.25 + */ 3.26 + 3.27 +/* 3.28 + * @test 3.29 + * @bug 6732484 3.30 + * @summary Bound error on wildcard code 3.31 + * @author Maurizio Cimadamore 3.32 + * @compile T6732484.java 3.33 + */ 3.34 + 3.35 +class T6732484 { 3.36 + class A<T extends A<T>> {} 3.37 + class B extends A<B> {} 3.38 + 3.39 + A<? super B> f; 3.40 +} 3.41 \ No newline at end of file