# HG changeset patch # User mcimadamore # Date 1207751444 -3600 # Node ID 3942d9cdc81ce7383af96ac27cc1b06a11799adb # Parent 39aee2be94a4f1f9df75eb44b311e43765315ed3 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 diff -r 39aee2be94a4 -r 3942d9cdc81c langtools/src/share/classes/com/sun/tools/javac/code/Type.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Wed Apr 09 15:04:35 2008 +0100 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Wed Apr 09 15:30:44 2008 +0100 @@ -640,6 +640,10 @@ return typarams_field; } + public boolean hasErasedSupertypes() { + return isRaw(); + } + public Type getEnclosingType() { return outer_field; } @@ -711,6 +715,17 @@ } } + public static class ErasedClassType extends ClassType { + public ErasedClassType(Type outer, TypeSymbol tsym) { + super(outer, List.nil(), tsym); + } + + @Override + public boolean hasErasedSupertypes() { + return true; + } + } + public static class ArrayType extends Type implements javax.lang.model.type.ArrayType { diff -r 39aee2be94a4 -r 3942d9cdc81c langtools/src/share/classes/com/sun/tools/javac/code/Types.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Wed Apr 09 15:04:35 2008 +0100 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Wed Apr 09 15:30:44 2008 +0100 @@ -1499,47 +1499,68 @@ * type parameters in t are deleted. */ public Type erasure(Type t) { + return erasure(t, false); + } + //where + private Type erasure(Type t, boolean recurse) { if (t.tag <= lastBaseTag) return t; /* fast special case */ else - return erasure.visit(t); + return erasure.visit(t, recurse); } // where - private UnaryVisitor erasure = new UnaryVisitor() { - public Type visitType(Type t, Void ignored) { + private SimpleVisitor erasure = new SimpleVisitor() { + public Type visitType(Type t, Boolean recurse) { if (t.tag <= lastBaseTag) return t; /*fast special case*/ else - return t.map(erasureFun); + return t.map(recurse ? erasureRecFun : erasureFun); } @Override - public Type visitWildcardType(WildcardType t, Void ignored) { - return erasure(upperBound(t)); - } - - @Override - public Type visitClassType(ClassType t, Void ignored) { - return t.tsym.erasure(Types.this); + public Type visitWildcardType(WildcardType t, Boolean recurse) { + return erasure(upperBound(t), recurse); } @Override - public Type visitTypeVar(TypeVar t, Void ignored) { - return erasure(t.bound); + public Type visitClassType(ClassType t, Boolean recurse) { + Type erased = t.tsym.erasure(Types.this); + if (recurse) { + erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym); + } + return erased; } @Override - public Type visitErrorType(ErrorType t, Void ignored) { + public Type visitTypeVar(TypeVar t, Boolean recurse) { + return erasure(t.bound, recurse); + } + + @Override + public Type visitErrorType(ErrorType t, Boolean recurse) { return t; } }; + private Mapping erasureFun = new Mapping ("erasure") { public Type apply(Type t) { return erasure(t); } }; + private Mapping erasureRecFun = new Mapping ("erasureRecursive") { + public Type apply(Type t) { return erasureRecursive(t); } + }; + public List erasure(List ts) { return Type.map(ts, erasureFun); } + + public Type erasureRecursive(Type t) { + return erasure(t, true); + } + + public List erasureRecursive(List ts) { + return Type.map(ts, erasureRecFun); + } // // @@ -1626,15 +1647,14 @@ if (t.supertype_field == null) { List actuals = classBound(t).allparams(); List formals = t.tsym.type.allparams(); - if (actuals.isEmpty()) { - if (formals.isEmpty()) - // Should not happen. See comments below in interfaces - t.supertype_field = supertype; - else - t.supertype_field = erasure(supertype); - } else { + if (t.hasErasedSupertypes()) { + t.supertype_field = erasureRecursive(supertype); + } else if (formals.nonEmpty()) { t.supertype_field = subst(supertype, formals, actuals); } + else { + t.supertype_field = supertype; + } } } return t.supertype_field; @@ -1708,18 +1728,15 @@ assert t != t.tsym.type : t.toString(); List actuals = t.allparams(); List formals = t.tsym.type.allparams(); - if (actuals.isEmpty()) { - if (formals.isEmpty()) { - // In this case t is not generic (nor raw). - // So this should not happen. - t.interfaces_field = interfaces; - } else { - t.interfaces_field = erasure(interfaces); - } - } else { + if (t.hasErasedSupertypes()) { + t.interfaces_field = erasureRecursive(interfaces); + } else if (formals.nonEmpty()) { t.interfaces_field = upperBounds(subst(interfaces, formals, actuals)); } + else { + t.interfaces_field = interfaces; + } } } return t.interfaces_field; diff -r 39aee2be94a4 -r 3942d9cdc81c langtools/test/tools/javac/generics/Casting5.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/Casting5.java Wed Apr 09 15:30:44 2008 +0100 @@ -0,0 +1,45 @@ +/* + * Copyright 2004 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 6559182 + * @summary Cast from a raw type with non-generic supertype to a raw type fails unexpectedly + * @author Maurizio Cimadamore + * + * @compile Casting5.java + */ + +class Casting5 { + static interface Super

{} + static class Y implements Super{} + static interface X extends Super{} + static class S extends Y {} + static interface T extends X {} + + public static void main(String... args) { + S s = null; // same if I use S + T t = null; // same if I use T + t = (T) s; + } +}