8071291: Compiler crashes trying to cast UnionType to IntersectionClassType

Fri, 21 Aug 2015 13:52:30 +0100

author
robm
date
Fri, 21 Aug 2015 13:52:30 +0100
changeset 2904
14891e981af0
parent 2903
a44348b50794
child 2905
f166261986cc
child 2977
70690e402d9e

8071291: Compiler crashes trying to cast UnionType to IntersectionClassType
Reviewed-by: mcimadamore

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
src/share/classes/com/sun/tools/javac/comp/Attr.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Check.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Infer.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/TransTypes.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/8071291/T8071291.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Type.java	Fri Aug 07 11:55:35 2015 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Type.java	Fri Aug 21 13:52:30 2015 +0100
     1.3 @@ -421,6 +421,14 @@
     1.4              && (tsym.flags() & COMPOUND) != 0;
     1.5      }
     1.6  
     1.7 +    public boolean isIntersection() {
     1.8 +        return false;
     1.9 +    }
    1.10 +
    1.11 +    public boolean isUnion() {
    1.12 +        return false;
    1.13 +    }
    1.14 +
    1.15      public boolean isInterface() {
    1.16          return (tsym.flags() & INTERFACE) != 0;
    1.17      }
    1.18 @@ -970,6 +978,11 @@
    1.19          }
    1.20  
    1.21          @Override
    1.22 +        public boolean isUnion() {
    1.23 +            return true;
    1.24 +        }
    1.25 +
    1.26 +        @Override
    1.27          public TypeKind getKind() {
    1.28              return TypeKind.UNION;
    1.29          }
    1.30 @@ -1003,6 +1016,11 @@
    1.31              return interfaces_field.prepend(supertype_field);
    1.32          }
    1.33  
    1.34 +        @Override
    1.35 +        public boolean isIntersection() {
    1.36 +            return true;
    1.37 +        }
    1.38 +
    1.39          public List<Type> getExplicitComponents() {
    1.40              return allInterfaces ?
    1.41                      interfaces_field :
     2.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Aug 07 11:55:35 2015 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Aug 21 13:52:30 2015 +0100
     2.3 @@ -1539,8 +1539,8 @@
     2.4                      }
     2.5                  }
     2.6  
     2.7 -                if (t.isCompound() || s.isCompound()) {
     2.8 -                    return !t.isCompound() ?
     2.9 +                if (t.isIntersection() || s.isIntersection()) {
    2.10 +                    return !t.isIntersection() ?
    2.11                              visitIntersectionType((IntersectionClassType)s.unannotatedType(), t, true) :
    2.12                              visitIntersectionType((IntersectionClassType)t.unannotatedType(), s, false);
    2.13                  }
    2.14 @@ -2255,19 +2255,28 @@
    2.15      }
    2.16      // </editor-fold>
    2.17  
    2.18 -    // <editor-fold defaultstate="collapsed" desc="makeCompoundType">
    2.19 +    // <editor-fold defaultstate="collapsed" desc="makeIntersectionType">
    2.20      /**
    2.21 -     * Make a compound type from non-empty list of types.  The list should be
    2.22 -     * ordered according to {@link Symbol#precedes(TypeSymbol,Types)}.
    2.23 +     * Make an intersection type from non-empty list of types.  The list should be ordered according to
    2.24 +     * {@link TypeSymbol#precedes(TypeSymbol, Types)}. Note that this might cause a symbol completion.
    2.25 +     * Hence, this version of makeIntersectionType may not be called during a classfile read.
    2.26       *
    2.27 -     * @param bounds            the types from which the compound type is formed
    2.28 -     * @param supertype         is objectType if all bounds are interfaces,
    2.29 -     *                          null otherwise.
    2.30 +     * @param bounds    the types from which the intersection type is formed
    2.31       */
    2.32 -    public Type makeCompoundType(List<Type> bounds) {
    2.33 -        return makeCompoundType(bounds, bounds.head.tsym.isInterface());
    2.34 +    public IntersectionClassType makeIntersectionType(List<Type> bounds) {
    2.35 +        return makeIntersectionType(bounds, bounds.head.tsym.isInterface());
    2.36      }
    2.37 -    public Type makeCompoundType(List<Type> bounds, boolean allInterfaces) {
    2.38 +
    2.39 +    /**
    2.40 +     * Make an intersection type from non-empty list of types.  The list should be ordered according to
    2.41 +     * {@link TypeSymbol#precedes(TypeSymbol, Types)}. This does not cause symbol completion as
    2.42 +     * an extra parameter indicates as to whether all bounds are interfaces - in which case the
    2.43 +     * supertype is implicitly assumed to be 'Object'.
    2.44 +     *
    2.45 +     * @param bounds        the types from which the intersection type is formed
    2.46 +     * @param allInterfaces are all bounds interface types?
    2.47 +     */
    2.48 +    public IntersectionClassType makeIntersectionType(List<Type> bounds, boolean allInterfaces) {
    2.49          Assert.check(bounds.nonEmpty());
    2.50          Type firstExplicitBound = bounds.head;
    2.51          if (allInterfaces) {
    2.52 @@ -2280,23 +2289,24 @@
    2.53                                  : names.empty,
    2.54                              null,
    2.55                              syms.noSymbol);
    2.56 -        bc.type = new IntersectionClassType(bounds, bc, allInterfaces);
    2.57 +        IntersectionClassType intersectionType = new IntersectionClassType(bounds, bc, allInterfaces);
    2.58 +        bc.type = intersectionType;
    2.59          bc.erasure_field = (bounds.head.hasTag(TYPEVAR)) ?
    2.60                  syms.objectType : // error condition, recover
    2.61                  erasure(firstExplicitBound);
    2.62          bc.members_field = new Scope(bc);
    2.63 -        return bc.type;
    2.64 +        return intersectionType;
    2.65      }
    2.66  
    2.67      /**
    2.68 -     * A convenience wrapper for {@link #makeCompoundType(List)}; the
    2.69 +     * A convenience wrapper for {@link #makeIntersectionType(List)}; the
    2.70       * arguments are converted to a list and passed to the other
    2.71       * method.  Note that this might cause a symbol completion.
    2.72 -     * Hence, this version of makeCompoundType may not be called
    2.73 +     * Hence, this version of makeIntersectionType may not be called
    2.74       * during a classfile read.
    2.75       */
    2.76 -    public Type makeCompoundType(Type bound1, Type bound2) {
    2.77 -        return makeCompoundType(List.of(bound1, bound2));
    2.78 +    public Type makeIntersectionType(Type bound1, Type bound2) {
    2.79 +        return makeIntersectionType(List.of(bound1, bound2));
    2.80      }
    2.81      // </editor-fold>
    2.82  
    2.83 @@ -2436,7 +2446,7 @@
    2.84          private final UnaryVisitor<List<Type>> directSupertypes = new UnaryVisitor<List<Type>>() {
    2.85  
    2.86              public List<Type> visitType(final Type type, final Void ignored) {
    2.87 -                if (!type.isCompound()) {
    2.88 +                if (!type.isIntersection()) {
    2.89                      final Type sup = supertype(type);
    2.90                      return (sup == Type.noType || sup == type || sup == null)
    2.91                          ? interfaces(type)
    2.92 @@ -2490,30 +2500,32 @@
    2.93  
    2.94      // <editor-fold defaultstate="collapsed" desc="setBounds">
    2.95      /**
    2.96 -     * Set the bounds field of the given type variable to reflect a
    2.97 -     * (possibly multiple) list of bounds.
    2.98 -     * @param t                 a type variable
    2.99 -     * @param bounds            the bounds, must be nonempty
   2.100 -     * @param supertype         is objectType if all bounds are interfaces,
   2.101 -     *                          null otherwise.
   2.102 +     * Same as {@link Types#setBounds(TypeVar, List, boolean)}, except that third parameter is computed directly,
   2.103 +     * as follows: if all all bounds are interface types, the computed supertype is Object,otherwise
   2.104 +     * the supertype is simply left null (in this case, the supertype is assumed to be the head of
   2.105 +     * the bound list passed as second argument). Note that this check might cause a symbol completion.
   2.106 +     * Hence, this version of setBounds may not be called during a classfile read.
   2.107 +     *
   2.108 +     * @param t         a type variable
   2.109 +     * @param bounds    the bounds, must be nonempty
   2.110       */
   2.111      public void setBounds(TypeVar t, List<Type> bounds) {
   2.112          setBounds(t, bounds, bounds.head.tsym.isInterface());
   2.113      }
   2.114  
   2.115      /**
   2.116 -     * Same as {@link #setBounds(Type.TypeVar,List,Type)}, except that
   2.117 -     * third parameter is computed directly, as follows: if all
   2.118 -     * all bounds are interface types, the computed supertype is Object,
   2.119 -     * otherwise the supertype is simply left null (in this case, the supertype
   2.120 -     * is assumed to be the head of the bound list passed as second argument).
   2.121 -     * Note that this check might cause a symbol completion. Hence, this version of
   2.122 -     * setBounds may not be called during a classfile read.
   2.123 +     * Set the bounds field of the given type variable to reflect a (possibly multiple) list of bounds.
   2.124 +     * This does not cause symbol completion as an extra parameter indicates as to whether all bounds
   2.125 +     * are interfaces - in which case the supertype is implicitly assumed to be 'Object'.
   2.126 +     *
   2.127 +     * @param t             a type variable
   2.128 +     * @param bounds        the bounds, must be nonempty
   2.129 +     * @param allInterfaces are all bounds interface types?
   2.130       */
   2.131      public void setBounds(TypeVar t, List<Type> bounds, boolean allInterfaces) {
   2.132          t.bound = bounds.tail.isEmpty() ?
   2.133                  bounds.head :
   2.134 -                makeCompoundType(bounds, allInterfaces);
   2.135 +                makeIntersectionType(bounds, allInterfaces);
   2.136          t.rank_field = -1;
   2.137      }
   2.138      // </editor-fold>
   2.139 @@ -3063,7 +3075,7 @@
   2.140                  if (st == supertype(t) && is == interfaces(t))
   2.141                      return t;
   2.142                  else
   2.143 -                    return makeCompoundType(is.prepend(st));
   2.144 +                    return makeIntersectionType(is.prepend(st));
   2.145              }
   2.146          }
   2.147  
   2.148 @@ -3566,7 +3578,7 @@
   2.149          else if (compound.tail.isEmpty())
   2.150              return compound.head;
   2.151          else
   2.152 -            return makeCompoundType(compound);
   2.153 +            return makeIntersectionType(compound);
   2.154      }
   2.155  
   2.156      /**
   2.157 @@ -3744,8 +3756,8 @@
   2.158                  synchronized (this) {
   2.159                      if (arraySuperType == null) {
   2.160                          // JLS 10.8: all arrays implement Cloneable and Serializable.
   2.161 -                        arraySuperType = makeCompoundType(List.of(syms.serializableType,
   2.162 -                                                                  syms.cloneableType), true);
   2.163 +                        arraySuperType = makeIntersectionType(List.of(syms.serializableType,
   2.164 +                                syms.cloneableType), true);
   2.165                      }
   2.166                  }
   2.167              }
   2.168 @@ -3811,7 +3823,7 @@
   2.169                      return glbFlattened(union(bounds, lowers), errT);
   2.170              }
   2.171          }
   2.172 -        return makeCompoundType(bounds);
   2.173 +        return makeIntersectionType(bounds);
   2.174      }
   2.175      // </editor-fold>
   2.176  
     3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Aug 07 11:55:35 2015 -0700
     3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Aug 21 13:52:30 2015 +0100
     3.3 @@ -2434,7 +2434,7 @@
     3.4  
     3.5              @Override
     3.6              public Type visitClassType(ClassType t, DiagnosticPosition pos) {
     3.7 -                return t.isCompound() ?
     3.8 +                return t.isIntersection() ?
     3.9                          visitIntersectionClassType((IntersectionClassType)t, pos) : t;
    3.10              }
    3.11  
    3.12 @@ -2465,8 +2465,7 @@
    3.13                      }
    3.14                      supertypes.append(i.tsym.type);
    3.15                  }
    3.16 -                IntersectionClassType notionalIntf =
    3.17 -                        (IntersectionClassType)types.makeCompoundType(supertypes.toList());
    3.18 +                IntersectionClassType notionalIntf = types.makeIntersectionType(supertypes.toList());
    3.19                  notionalIntf.allparams_field = targs.toList();
    3.20                  notionalIntf.tsym.flags_field |= INTERFACE;
    3.21                  return notionalIntf.tsym;
    3.22 @@ -4032,7 +4031,7 @@
    3.23          } else if (bounds.length() == 1) {
    3.24              return bounds.head.type;
    3.25          } else {
    3.26 -            Type owntype = types.makeCompoundType(TreeInfo.types(bounds));
    3.27 +            Type owntype = types.makeIntersectionType(TreeInfo.types(bounds));
    3.28              // ... the variable's bound is a class type flagged COMPOUND
    3.29              // (see comment for TypeVar.bound).
    3.30              // In this case, generate a class tree that represents the
     4.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Aug 07 11:55:35 2015 -0700
     4.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Aug 21 13:52:30 2015 +0100
     4.3 @@ -1813,7 +1813,7 @@
     4.4                                              Type t1,
     4.5                                              Type t2) {
     4.6          return checkCompatibleAbstracts(pos, t1, t2,
     4.7 -                                        types.makeCompoundType(t1, t2));
     4.8 +                                        types.makeIntersectionType(t1, t2));
     4.9      }
    4.10  
    4.11      public boolean checkCompatibleAbstracts(DiagnosticPosition pos,
     5.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Aug 07 11:55:35 2015 -0700
     5.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Aug 21 13:52:30 2015 +0100
     5.3 @@ -373,7 +373,7 @@
     5.4              List<Type> upperBounds = uv.getBounds(InferenceBound.UPPER);
     5.5              if (Type.containsAny(upperBounds, vars)) {
     5.6                  TypeSymbol fresh_tvar = new TypeVariableSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
     5.7 -                fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null);
     5.8 +                fresh_tvar.type = new TypeVar(fresh_tvar, types.makeIntersectionType(uv.getBounds(InferenceBound.UPPER)), null);
     5.9                  todo.append(uv);
    5.10                  uv.inst = fresh_tvar.type;
    5.11              } else if (upperBounds.nonEmpty()) {
     6.1 --- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Aug 07 11:55:35 2015 -0700
     6.2 +++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Aug 21 13:52:30 2015 +0100
     6.3 @@ -750,7 +750,7 @@
     6.4          Type originalTarget = tree.type;
     6.5          tree.type = erasure(tree.type);
     6.6          tree.expr = translate(tree.expr, tree.type);
     6.7 -        if (originalTarget.isCompound()) {
     6.8 +        if (originalTarget.isIntersection()) {
     6.9              Type.IntersectionClassType ict = (Type.IntersectionClassType)originalTarget;
    6.10              for (Type c : ict.getExplicitComponents()) {
    6.11                  Type ec = erasure(c);
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/tools/javac/multicatch/8071291/T8071291.java	Fri Aug 21 13:52:30 2015 +0100
     7.3 @@ -0,0 +1,49 @@
     7.4 +/*
     7.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.
    7.11 + *
    7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.15 + * version 2 for more details (a copy is included in the LICENSE file that
    7.16 + * accompanied this code).
    7.17 + *
    7.18 + * You should have received a copy of the GNU General Public License version
    7.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.21 + *
    7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    7.23 + * or visit www.oracle.com if you need additional information or have any
    7.24 + * questions.
    7.25 + */
    7.26 +
    7.27 +/*
    7.28 + * @test
    7.29 + * @bug 8071291
    7.30 + * @summary Compiler crashes trying to cast UnionType to IntersectionClassType
    7.31 + * @compile T8071291.java
    7.32 + */
    7.33 +
    7.34 +class T8071291 {
    7.35 +
    7.36 +    interface A { }
    7.37 +    class Exception1 extends Exception implements A { }
    7.38 +    class Exception2 extends Exception implements A { }
    7.39 +
    7.40 +    void test(boolean cond) {
    7.41 +        try {
    7.42 +            if (cond) {
    7.43 +                throw new Exception1();
    7.44 +            } else {
    7.45 +                throw new Exception2();
    7.46 +            }
    7.47 +        }
    7.48 +        catch (Exception1|Exception2 x) {
    7.49 +            if (x instanceof Exception1) { }
    7.50 +        }
    7.51 +    }
    7.52 +}

mercurial