Wed, 09 Apr 2008 15:30:44 +0100
6559182: Cast from a raw type with non-generic supertype to a raw type fails unexpectedly
Summary: Javac doesn't conform to JLS 4.8 - all the supertypes of a raw type must be erased
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Type.java Wed Apr 09 15:04:35 2008 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Type.java Wed Apr 09 15:30:44 2008 +0100 1.3 @@ -640,6 +640,10 @@ 1.4 return typarams_field; 1.5 } 1.6 1.7 + public boolean hasErasedSupertypes() { 1.8 + return isRaw(); 1.9 + } 1.10 + 1.11 public Type getEnclosingType() { 1.12 return outer_field; 1.13 } 1.14 @@ -711,6 +715,17 @@ 1.15 } 1.16 } 1.17 1.18 + public static class ErasedClassType extends ClassType { 1.19 + public ErasedClassType(Type outer, TypeSymbol tsym) { 1.20 + super(outer, List.<Type>nil(), tsym); 1.21 + } 1.22 + 1.23 + @Override 1.24 + public boolean hasErasedSupertypes() { 1.25 + return true; 1.26 + } 1.27 + } 1.28 + 1.29 public static class ArrayType extends Type 1.30 implements javax.lang.model.type.ArrayType { 1.31
2.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Wed Apr 09 15:04:35 2008 +0100 2.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Wed Apr 09 15:30:44 2008 +0100 2.3 @@ -1499,47 +1499,68 @@ 2.4 * type parameters in t are deleted. 2.5 */ 2.6 public Type erasure(Type t) { 2.7 + return erasure(t, false); 2.8 + } 2.9 + //where 2.10 + private Type erasure(Type t, boolean recurse) { 2.11 if (t.tag <= lastBaseTag) 2.12 return t; /* fast special case */ 2.13 else 2.14 - return erasure.visit(t); 2.15 + return erasure.visit(t, recurse); 2.16 } 2.17 // where 2.18 - private UnaryVisitor<Type> erasure = new UnaryVisitor<Type>() { 2.19 - public Type visitType(Type t, Void ignored) { 2.20 + private SimpleVisitor<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() { 2.21 + public Type visitType(Type t, Boolean recurse) { 2.22 if (t.tag <= lastBaseTag) 2.23 return t; /*fast special case*/ 2.24 else 2.25 - return t.map(erasureFun); 2.26 + return t.map(recurse ? erasureRecFun : erasureFun); 2.27 } 2.28 2.29 @Override 2.30 - public Type visitWildcardType(WildcardType t, Void ignored) { 2.31 - return erasure(upperBound(t)); 2.32 + public Type visitWildcardType(WildcardType t, Boolean recurse) { 2.33 + return erasure(upperBound(t), recurse); 2.34 } 2.35 2.36 @Override 2.37 - public Type visitClassType(ClassType t, Void ignored) { 2.38 - return t.tsym.erasure(Types.this); 2.39 + public Type visitClassType(ClassType t, Boolean recurse) { 2.40 + Type erased = t.tsym.erasure(Types.this); 2.41 + if (recurse) { 2.42 + erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym); 2.43 + } 2.44 + return erased; 2.45 } 2.46 2.47 @Override 2.48 - public Type visitTypeVar(TypeVar t, Void ignored) { 2.49 - return erasure(t.bound); 2.50 + public Type visitTypeVar(TypeVar t, Boolean recurse) { 2.51 + return erasure(t.bound, recurse); 2.52 } 2.53 2.54 @Override 2.55 - public Type visitErrorType(ErrorType t, Void ignored) { 2.56 + public Type visitErrorType(ErrorType t, Boolean recurse) { 2.57 return t; 2.58 } 2.59 }; 2.60 + 2.61 private Mapping erasureFun = new Mapping ("erasure") { 2.62 public Type apply(Type t) { return erasure(t); } 2.63 }; 2.64 2.65 + private Mapping erasureRecFun = new Mapping ("erasureRecursive") { 2.66 + public Type apply(Type t) { return erasureRecursive(t); } 2.67 + }; 2.68 + 2.69 public List<Type> erasure(List<Type> ts) { 2.70 return Type.map(ts, erasureFun); 2.71 } 2.72 + 2.73 + public Type erasureRecursive(Type t) { 2.74 + return erasure(t, true); 2.75 + } 2.76 + 2.77 + public List<Type> erasureRecursive(List<Type> ts) { 2.78 + return Type.map(ts, erasureRecFun); 2.79 + } 2.80 // </editor-fold> 2.81 2.82 // <editor-fold defaultstate="collapsed" desc="makeCompoundType"> 2.83 @@ -1626,15 +1647,14 @@ 2.84 if (t.supertype_field == null) { 2.85 List<Type> actuals = classBound(t).allparams(); 2.86 List<Type> formals = t.tsym.type.allparams(); 2.87 - if (actuals.isEmpty()) { 2.88 - if (formals.isEmpty()) 2.89 - // Should not happen. See comments below in interfaces 2.90 - t.supertype_field = supertype; 2.91 - else 2.92 - t.supertype_field = erasure(supertype); 2.93 - } else { 2.94 + if (t.hasErasedSupertypes()) { 2.95 + t.supertype_field = erasureRecursive(supertype); 2.96 + } else if (formals.nonEmpty()) { 2.97 t.supertype_field = subst(supertype, formals, actuals); 2.98 } 2.99 + else { 2.100 + t.supertype_field = supertype; 2.101 + } 2.102 } 2.103 } 2.104 return t.supertype_field; 2.105 @@ -1708,18 +1728,15 @@ 2.106 assert t != t.tsym.type : t.toString(); 2.107 List<Type> actuals = t.allparams(); 2.108 List<Type> formals = t.tsym.type.allparams(); 2.109 - if (actuals.isEmpty()) { 2.110 - if (formals.isEmpty()) { 2.111 - // In this case t is not generic (nor raw). 2.112 - // So this should not happen. 2.113 - t.interfaces_field = interfaces; 2.114 - } else { 2.115 - t.interfaces_field = erasure(interfaces); 2.116 - } 2.117 - } else { 2.118 + if (t.hasErasedSupertypes()) { 2.119 + t.interfaces_field = erasureRecursive(interfaces); 2.120 + } else if (formals.nonEmpty()) { 2.121 t.interfaces_field = 2.122 upperBounds(subst(interfaces, formals, actuals)); 2.123 } 2.124 + else { 2.125 + t.interfaces_field = interfaces; 2.126 + } 2.127 } 2.128 } 2.129 return t.interfaces_field;
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/generics/Casting5.java Wed Apr 09 15:30:44 2008 +0100 3.3 @@ -0,0 +1,45 @@ 3.4 +/* 3.5 + * Copyright 2004 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 6559182 3.30 + * @summary Cast from a raw type with non-generic supertype to a raw type fails unexpectedly 3.31 + * @author Maurizio Cimadamore 3.32 + * 3.33 + * @compile Casting5.java 3.34 + */ 3.35 + 3.36 +class Casting5 { 3.37 + static interface Super<P> {} 3.38 + static class Y implements Super<Integer>{} 3.39 + static interface X extends Super<Double>{} 3.40 + static class S<L> extends Y {} 3.41 + static interface T<L> extends X {} 3.42 + 3.43 + public static void main(String... args) { 3.44 + S s = null; // same if I use S<Byte> 3.45 + T t = null; // same if I use T<Byte> 3.46 + t = (T) s; 3.47 + } 3.48 +}