6559182: Cast from a raw type with non-generic supertype to a raw type fails unexpectedly

Wed, 09 Apr 2008 15:30:44 +0100

author
mcimadamore
date
Wed, 09 Apr 2008 15:30:44 +0100
changeset 30
a1d1f335633f
parent 29
6522ea413d23
child 31
627deea1ea4f

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

src/share/classes/com/sun/tools/javac/code/Type.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Types.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/Casting5.java file | annotate | diff | comparison | revisions
     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 +}

mercurial