8021339: Compile-time error during casting array to intersection

Tue, 01 Oct 2013 17:41:57 -0400

author
emc
date
Tue, 01 Oct 2013 17:41:57 -0400
changeset 2079
de1c5dbe6c28
parent 2078
1a3e8347f3dd
child 2080
1e6088da1740

8021339: Compile-time error during casting array to intersection
Summary: Add ability to have arrays in intersection types.
Reviewed-by: jjg, vromero

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
test/tools/javac/ArraysInIntersections.java file | annotate | diff | comparison | revisions
test/tools/javac/InferArraysInIntersections.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/typevars/6680106/T6680106.out file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java	Tue Oct 01 17:03:31 2013 +0400
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Tue Oct 01 17:41:57 2013 -0400
     1.3 @@ -244,7 +244,7 @@
     1.4              public Type visitClassType(ClassType t, Symbol sym) {
     1.5                  if (t.tsym == sym)
     1.6                      return t;
     1.7 -                Type base = asSuper(sym.type, t.tsym);
     1.8 +                Type base = asSuper(sym.type, t);
     1.9                  if (base == null)
    1.10                      return null;
    1.11                  ListBuffer<Type> from = new ListBuffer<Type>();
    1.12 @@ -687,7 +687,7 @@
    1.13                          (t.flags() & SYNTHETIC) == 0;
    1.14              }
    1.15          };
    1.16 -        private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) {
    1.17 +        private boolean pendingBridges(ClassSymbol origin, TypeSymbol sym) {
    1.18              //a symbol will be completed from a classfile if (a) symbol has
    1.19              //an associated file object with CLASS kind and (b) the symbol has
    1.20              //not been entered
    1.21 @@ -696,11 +696,11 @@
    1.22                      enter.getEnv(origin) == null) {
    1.23                  return false;
    1.24              }
    1.25 -            if (origin == s) {
    1.26 +            if (origin == sym) {
    1.27                  return true;
    1.28              }
    1.29              for (Type t : interfaces(origin.type)) {
    1.30 -                if (pendingBridges((ClassSymbol)t.tsym, s)) {
    1.31 +                if (pendingBridges((ClassSymbol)t.tsym, sym)) {
    1.32                      return true;
    1.33                  }
    1.34              }
    1.35 @@ -761,7 +761,7 @@
    1.36              } else if (t.hasTag(TYPEVAR)) {
    1.37                  return isSubtypeUnchecked(t.getUpperBound(), s, warn);
    1.38              } else if (!s.isRaw()) {
    1.39 -                Type t2 = asSuper(t, s.tsym);
    1.40 +                Type t2 = asSuper(t, s);
    1.41                  if (t2 != null && t2.isRaw()) {
    1.42                      if (isReifiable(s)) {
    1.43                          warn.silentWarn(LintCategory.UNCHECKED);
    1.44 @@ -914,7 +914,7 @@
    1.45  
    1.46              @Override
    1.47              public Boolean visitClassType(ClassType t, Type s) {
    1.48 -                Type sup = asSuper(t, s.tsym);
    1.49 +                Type sup = asSuper(t, s);
    1.50                  return sup != null
    1.51                      && sup.tsym == s.tsym
    1.52                      // You're not allowed to write
    1.53 @@ -1935,30 +1935,42 @@
    1.54       * @param t a type
    1.55       * @param sym a symbol
    1.56       */
    1.57 -    public Type asSuper(Type t, Symbol sym) {
    1.58 -        return asSuper.visit(t, sym);
    1.59 +    public Type asSuper(Type t, Symbol s) {
    1.60 +        return asSuper(t, s.type);
    1.61 +    }
    1.62 +
    1.63 +    public Type asSuper(Type t, Type s) {
    1.64 +        return asSuper.visit(t, s);
    1.65      }
    1.66      // where
    1.67 -        private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() {
    1.68 -
    1.69 -            public Type visitType(Type t, Symbol sym) {
    1.70 +        private SimpleVisitor<Type,Type> asSuper = new SimpleVisitor<Type,Type>() {
    1.71 +
    1.72 +            public Type visitType(Type t, Type s) {
    1.73                  return null;
    1.74              }
    1.75  
    1.76              @Override
    1.77 -            public Type visitClassType(ClassType t, Symbol sym) {
    1.78 -                if (t.tsym == sym)
    1.79 +            public Type visitClassType(ClassType t, Type s) {
    1.80 +                if (t.tsym == s.tsym)
    1.81                      return t;
    1.82  
    1.83                  Type st = supertype(t);
    1.84 -                if (st.hasTag(CLASS) || st.hasTag(TYPEVAR) || st.hasTag(ERROR)) {
    1.85 -                    Type x = asSuper(st, sym);
    1.86 +
    1.87 +                switch(st.getTag()) {
    1.88 +                default: break;
    1.89 +                case CLASS:
    1.90 +                case ARRAY:
    1.91 +                case TYPEVAR:
    1.92 +                case ERROR: {
    1.93 +                    Type x = asSuper(st, s);
    1.94                      if (x != null)
    1.95                          return x;
    1.96 +                } break;
    1.97                  }
    1.98 -                if ((sym.flags() & INTERFACE) != 0) {
    1.99 +
   1.100 +                if ((s.tsym.flags() & INTERFACE) != 0) {
   1.101                      for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
   1.102 -                        Type x = asSuper(l.head, sym);
   1.103 +                        Type x = asSuper(l.head, s);
   1.104                          if (x != null)
   1.105                              return x;
   1.106                      }
   1.107 @@ -1967,22 +1979,20 @@
   1.108              }
   1.109  
   1.110              @Override
   1.111 -            public Type visitArrayType(ArrayType t, Symbol sym) {
   1.112 -                return isSubtype(t, sym.type) ? sym.type : null;
   1.113 +            public Type visitArrayType(ArrayType t, Type s) {
   1.114 +                return isSubtype(t, s) ? s : null;
   1.115              }
   1.116  
   1.117              @Override
   1.118 -            public Type visitTypeVar(TypeVar t, Symbol sym) {
   1.119 -                if (t.tsym == sym)
   1.120 +            public Type visitTypeVar(TypeVar t, Type s) {
   1.121 +                if (t.tsym == s.tsym)
   1.122                      return t;
   1.123                  else
   1.124 -                    return asSuper(t.bound, sym);
   1.125 +                    return asSuper(t.bound, s);
   1.126              }
   1.127  
   1.128              @Override
   1.129 -            public Type visitErrorType(ErrorType t, Symbol sym) {
   1.130 -                return t;
   1.131 -            }
   1.132 +            public Type visitErrorType(ErrorType t, Type s) { return t; }
   1.133          };
   1.134  
   1.135      /**
   1.136 @@ -3563,9 +3573,9 @@
   1.137              //step 3 - for each element G in MEC, compute lci(Inv(G))
   1.138              List<Type> candidates = List.nil();
   1.139              for (Type erasedSupertype : mec) {
   1.140 -                List<Type> lci = List.of(asSuper(ts.head, erasedSupertype.tsym));
   1.141 +                List<Type> lci = List.of(asSuper(ts.head, erasedSupertype));
   1.142                  for (Type t : ts) {
   1.143 -                    lci = intersect(lci, List.of(asSuper(t, erasedSupertype.tsym)));
   1.144 +                    lci = intersect(lci, List.of(asSuper(t, erasedSupertype)));
   1.145                  }
   1.146                  candidates = candidates.appendList(lci);
   1.147              }
   1.148 @@ -3985,7 +3995,7 @@
   1.149          // The arguments to the supers could be unified here to
   1.150          // get a more accurate analysis
   1.151          while (commonSupers.nonEmpty()) {
   1.152 -            Type t1 = asSuper(from, commonSupers.head.tsym);
   1.153 +            Type t1 = asSuper(from, commonSupers.head);
   1.154              Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym);
   1.155              if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
   1.156                  return false;
   1.157 @@ -4016,7 +4026,7 @@
   1.158              from = target;
   1.159          }
   1.160          Assert.check((from.tsym.flags() & FINAL) != 0);
   1.161 -        Type t1 = asSuper(from, to.tsym);
   1.162 +        Type t1 = asSuper(from, to);
   1.163          if (t1 == null) return false;
   1.164          Type t2 = to;
   1.165          if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
     2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Oct 01 17:03:31 2013 +0400
     2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Oct 01 17:41:57 2013 -0400
     2.3 @@ -58,6 +58,7 @@
     2.4  import static com.sun.tools.javac.code.Kinds.ERRONEOUS;
     2.5  import static com.sun.tools.javac.code.TypeTag.*;
     2.6  import static com.sun.tools.javac.code.TypeTag.WILDCARD;
     2.7 +import static com.sun.tools.javac.code.TypeTag.ARRAY;
     2.8  import static com.sun.tools.javac.tree.JCTree.Tag.*;
     2.9  
    2.10  /** This is the main context-dependent analysis phase in GJC. It
    2.11 @@ -797,28 +798,32 @@
    2.12                     JCTree tree,
    2.13                     Env<AttrContext> env,
    2.14                     boolean classExpected,
    2.15 -                   boolean interfaceExpected,
    2.16 +                   boolean interfaceOrArrayExpected,
    2.17                     boolean checkExtensible) {
    2.18          if (t.isErroneous())
    2.19              return t;
    2.20 -        if (t.hasTag(TYPEVAR) && !classExpected && !interfaceExpected) {
    2.21 +        if (t.hasTag(TYPEVAR) && !classExpected && !interfaceOrArrayExpected) {
    2.22              // check that type variable is already visible
    2.23              if (t.getUpperBound() == null) {
    2.24                  log.error(tree.pos(), "illegal.forward.ref");
    2.25                  return types.createErrorType(t);
    2.26              }
    2.27 +        } else if (classExpected) {
    2.28 +            t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics);
    2.29          } else {
    2.30 -            t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics);
    2.31 +            t = chk.checkClassOrArrayType(tree.pos(), t,
    2.32 +                                          checkExtensible|!allowGenerics);
    2.33          }
    2.34 -        if (interfaceExpected && (t.tsym.flags() & INTERFACE) == 0) {
    2.35 +        if (interfaceOrArrayExpected &&
    2.36 +            !(t.tsym.isInterface() || t.getTag() == ARRAY)) {
    2.37              log.error(tree.pos(), "intf.expected.here");
    2.38              // return errType is necessary since otherwise there might
    2.39              // be undetected cycles which cause attribution to loop
    2.40              return types.createErrorType(t);
    2.41          } else if (checkExtensible &&
    2.42                     classExpected &&
    2.43 -                   (t.tsym.flags() & INTERFACE) != 0) {
    2.44 -                log.error(tree.pos(), "no.intf.expected.here");
    2.45 +                   t.tsym.isInterface()) {
    2.46 +            log.error(tree.pos(), "no.intf.expected.here");
    2.47              return types.createErrorType(t);
    2.48          }
    2.49          if (checkExtensible &&
    2.50 @@ -829,6 +834,12 @@
    2.51          chk.checkNonCyclic(tree.pos(), t);
    2.52          return t;
    2.53      }
    2.54 +    //where
    2.55 +        private Object asTypeParam(Type t) {
    2.56 +            return (t.hasTag(TYPEVAR))
    2.57 +                                    ? diags.fragment("type.parameter", t)
    2.58 +                                    : t;
    2.59 +        }
    2.60  
    2.61      Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) {
    2.62          Assert.check((env.enclClass.sym.flags() & ENUM) != 0);
     3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Tue Oct 01 17:03:31 2013 +0400
     3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Tue Oct 01 17:41:57 2013 -0400
     3.3 @@ -706,6 +706,37 @@
     3.4          return t;
     3.5      }
     3.6  
     3.7 +    // Analog of checkClassType that calls checkClassOrArrayType instead
     3.8 +    Type checkClassOrArrayType(DiagnosticPosition pos,
     3.9 +                               Type t, boolean noBounds) {
    3.10 +        t = checkClassOrArrayType(pos, t);
    3.11 +        if (noBounds && t.isParameterized()) {
    3.12 +            List<Type> args = t.getTypeArguments();
    3.13 +            while (args.nonEmpty()) {
    3.14 +                if (args.head.hasTag(WILDCARD))
    3.15 +                    return typeTagError(pos,
    3.16 +                                        diags.fragment("type.req.exact"),
    3.17 +                                        args.head);
    3.18 +                args = args.tail;
    3.19 +            }
    3.20 +        }
    3.21 +        return t;
    3.22 +    }
    3.23 +
    3.24 +    /** Check that type is a reifiable class, interface or array type.
    3.25 +     *  @param pos           Position to be used for error reporting.
    3.26 +     *  @param t             The type to be checked.
    3.27 +     */
    3.28 +    Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) {
    3.29 +        t = checkClassOrArrayType(pos, t);
    3.30 +        if (!t.isErroneous() && !types.isReifiable(t)) {
    3.31 +            log.error(pos, "illegal.generic.type.for.instof");
    3.32 +            return types.createErrorType(t);
    3.33 +        } else {
    3.34 +            return t;
    3.35 +        }
    3.36 +    }
    3.37 +
    3.38      /** Check that type is a reference type, i.e. a class, interface or array type
    3.39       *  or a type variable.
    3.40       *  @param pos           Position to be used for error reporting.
    3.41 @@ -2210,6 +2241,9 @@
    3.42              seen = seen.prepend(tv);
    3.43              for (Type b : types.getBounds(tv))
    3.44                  checkNonCyclic1(pos, b, seen);
    3.45 +        } else if (t.hasTag(ARRAY)) {
    3.46 +            final ArrayType at = (ArrayType)t.unannotatedType();
    3.47 +            checkNonCyclic1(pos, at.elemtype, seen);
    3.48          }
    3.49      }
    3.50  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/tools/javac/ArraysInIntersections.java	Tue Oct 01 17:41:57 2013 -0400
     4.3 @@ -0,0 +1,39 @@
     4.4 +/*
     4.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.
    4.11 + *
    4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.15 + * version 2 for more details (a copy is included in the LICENSE file that
    4.16 + * accompanied this code).
    4.17 + *
    4.18 + * You should have received a copy of the GNU General Public License version
    4.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.21 + *
    4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.23 + * or visit www.oracle.com if you need additional information or have any
    4.24 + * questions.
    4.25 + */
    4.26 +
    4.27 +/*
    4.28 + * @test
    4.29 + * @bug 8021339
    4.30 + * @summary Allow arrays in intersection types
    4.31 + * @compile ArraysInIntersections.java
    4.32 + */
    4.33 +
    4.34 +import java.io.Serializable;
    4.35 +
    4.36 +public class ArraysInIntersections<T extends Serializable & Integer[]> {
    4.37 +
    4.38 +    public <S extends Serializable & Integer[]> Object m() {
    4.39 +        return (Serializable & Integer[]) new Integer[1];
    4.40 +    }
    4.41 +
    4.42 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/tools/javac/InferArraysInIntersections.java	Tue Oct 01 17:41:57 2013 -0400
     5.3 @@ -0,0 +1,38 @@
     5.4 +/*
     5.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.
    5.11 + *
    5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.15 + * version 2 for more details (a copy is included in the LICENSE file that
    5.16 + * accompanied this code).
    5.17 + *
    5.18 + * You should have received a copy of the GNU General Public License version
    5.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.21 + *
    5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.23 + * or visit www.oracle.com if you need additional information or have any
    5.24 + * questions.
    5.25 + */
    5.26 +
    5.27 +/*
    5.28 + * @test
    5.29 + * @bug 8021339
    5.30 + * @summary Allow arrays in intersection types
    5.31 + * @compile -doe -XDrawDiagnostics InferArraysInIntersections.java
    5.32 + */
    5.33 +import java.util.*;
    5.34 +
    5.35 +class InferArraysInIntersections {
    5.36 +   <T> T m(List<? super T> t) { return null; }
    5.37 +
    5.38 +   void test(List<char[]> lc) {
    5.39 +      Runnable r = m(lc); //inference fails here
    5.40 +   }
    5.41 +}
     6.1 --- a/test/tools/javac/generics/typevars/6680106/T6680106.out	Tue Oct 01 17:03:31 2013 +0400
     6.2 +++ b/test/tools/javac/generics/typevars/6680106/T6680106.out	Tue Oct 01 17:41:57 2013 -0400
     6.3 @@ -1,13 +1,7 @@
     6.4 -T6680106.java:11:25: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
     6.5 -T6680106.java:12:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
     6.6 -T6680106.java:12:40: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
     6.7 -T6680106.java:13:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
     6.8 -T6680106.java:13:40: compiler.err.type.found.req: U[], (compiler.misc.type.req.class)
     6.9 -T6680106.java:13:55: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
    6.10 -T6680106.java:14:30: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
    6.11 -T6680106.java:15:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
    6.12 -T6680106.java:15:50: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
    6.13 -T6680106.java:16:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
    6.14 -T6680106.java:16:50: compiler.err.type.found.req: U[], (compiler.misc.type.req.class)
    6.15 -T6680106.java:16:70: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
    6.16 -12 errors
    6.17 +T6680106.java:11:14: compiler.err.cyclic.inheritance: T
    6.18 +T6680106.java:12:14: compiler.err.cyclic.inheritance: T
    6.19 +T6680106.java:13:14: compiler.err.cyclic.inheritance: T
    6.20 +T6680106.java:14:14: compiler.err.cyclic.inheritance: T
    6.21 +T6680106.java:15:14: compiler.err.cyclic.inheritance: T
    6.22 +T6680106.java:16:14: compiler.err.cyclic.inheritance: T
    6.23 +6 errors

mercurial