Wed, 19 May 2010 16:41:57 +0100
6880344: Recursive type parameters do not compile
Summary: Issue in type-variable substitution causes valid code to be rejected
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Thu May 13 11:30:28 2010 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Wed May 19 16:41:57 2010 +0100 1.3 @@ -588,10 +588,21 @@ 1.4 case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: 1.5 case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE: 1.6 return t.tag == s.tag; 1.7 - case TYPEVAR: 1.8 - return s.isSuperBound() 1.9 - && !s.isExtendsBound() 1.10 - && visit(t, upperBound(s)); 1.11 + case TYPEVAR: { 1.12 + if (s.tag == TYPEVAR) { 1.13 + //type-substitution does not preserve type-var types 1.14 + //check that type var symbols and bounds are indeed the same 1.15 + return t.tsym == s.tsym && 1.16 + visit(t.getUpperBound(), s.getUpperBound()); 1.17 + } 1.18 + else { 1.19 + //special case for s == ? super X, where upper(s) = u 1.20 + //check that u == t, where u has been set by Type.withTypeVar 1.21 + return s.isSuperBound() && 1.22 + !s.isExtendsBound() && 1.23 + visit(t, upperBound(s)); 1.24 + } 1.25 + } 1.26 default: 1.27 throw new AssertionError("isSameType " + t.tag); 1.28 }
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Thu May 13 11:30:28 2010 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Wed May 19 16:41:57 2010 +0100 2.3 @@ -915,7 +915,7 @@ 2.4 List<Type> actuals = tree.type.allparams(); 2.5 List<JCExpression> args = tree.arguments; 2.6 List<Type> forms = tree.type.tsym.type.getTypeArguments(); 2.7 - ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>(); 2.8 + ListBuffer<Type> tvars_buf = new ListBuffer<Type>(); 2.9 2.10 // For matching pairs of actual argument types `a' and 2.11 // formal type parameters with declared bound `b' ... 2.12 @@ -946,12 +946,15 @@ 2.13 } 2.14 2.15 args = tree.arguments; 2.16 - List<TypeVar> tvars = tvars_buf.toList(); 2.17 + List<Type> tvars = tvars_buf.toList(); 2.18 2.19 while (args.nonEmpty() && tvars.nonEmpty()) { 2.20 + Type actual = types.subst(args.head.type, 2.21 + tree.type.tsym.type.getTypeArguments(), 2.22 + tvars_buf.toList()); 2.23 checkExtends(args.head.pos(), 2.24 - args.head.type, 2.25 - tvars.head); 2.26 + actual, 2.27 + (TypeVar)tvars.head); 2.28 args = args.tail; 2.29 tvars = tvars.tail; 2.30 }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/generics/typevars/T6880344.java Wed May 19 16:41:57 2010 +0100 3.3 @@ -0,0 +1,40 @@ 3.4 +/* 3.5 + * Copyright 2009 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 6880344 3.30 + * @summary Recursive type parameters do not compile 3.31 + * @author mcimadamore 3.32 + * @compile T6880344.java 3.33 + */ 3.34 + 3.35 +class T6880344 { 3.36 + static class A<X1 extends G<X1>> { 3.37 + public A<N<X1>> xyz; 3.38 + } 3.39 + 3.40 + static class N<X2 extends G<X2>> implements G<N<X2>> { } 3.41 + 3.42 + interface G<X3 extends G<X3>> { } 3.43 +}