8042338: Refactor Types.upperBound to treat wildcards and variables separately
authordlsmith
Tue, 27 May 2014 16:32:56 -0600
changeset 24612 75dc732b45af
parent 24611 8848a1bca14f
child 24613 dbec02c24c7a
8042338: Refactor Types.upperBound to treat wildcards and variables separately Reviewed-by: vromero
langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java
langtools/src/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java
langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Tue May 27 14:23:55 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Tue May 27 16:32:56 2014 -0600
@@ -394,7 +394,7 @@
                 paramTypes = lb.toList();
             }
 
-            ClassSymbol sym = (ClassSymbol) types.upperBound(tsym.type).tsym;
+            ClassSymbol sym = (ClassSymbol) types.cvarUpperBound(tsym.type).tsym;
 
             Symbol msym = (memberName == sym.name)
                     ? findConstructor(sym, paramTypes)
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Tue May 27 14:23:55 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Tue May 27 16:32:56 2014 -0600
@@ -118,37 +118,34 @@
     }
     // </editor-fold>
 
-    // <editor-fold defaultstate="collapsed" desc="upperBound">
+    // <editor-fold defaultstate="collapsed" desc="bounds">
     /**
-     * The "rvalue conversion".<br>
-     * The upper bound of most types is the type
-     * itself.  Wildcards, on the other hand have upper
-     * and lower bounds.
-     * @param t a type
-     * @return the upper bound of the given type
+     * Get a wildcard's upper bound, returning non-wildcards unchanged.
+     * @param t a type argument, either a wildcard or a type
      */
-    public Type upperBound(Type t) {
-        return upperBound.visit(t);
+    public Type wildUpperBound(Type t) {
+        if (t.hasTag(WILDCARD)) {
+            WildcardType w = (WildcardType) t;
+            if (w.isSuperBound())
+                return w.bound == null ? syms.objectType : w.bound.bound;
+            else
+                return wildUpperBound(w.type);
+        }
+        else return t;
     }
-    // where
-        private final MapVisitor<Void> upperBound = new MapVisitor<Void>() {
-
-            @Override
-            public Type visitWildcardType(WildcardType t, Void ignored) {
-                if (t.isSuperBound())
-                    return t.bound == null ? syms.objectType : t.bound.bound;
-                else
-                    return visit(t.type);
-            }
-
-            @Override
-            public Type visitCapturedType(CapturedType t, Void ignored) {
-                return visit(t.bound);
-            }
-        };
-    // </editor-fold>
-
-    // <editor-fold defaultstate="collapsed" desc="wildLowerBound">
+
+    /**
+     * Get a capture variable's upper bound, returning other types unchanged.
+     * @param t a type
+     */
+    public Type cvarUpperBound(Type t) {
+        if (t.hasTag(TYPEVAR)) {
+            TypeVar v = (TypeVar) t;
+            return v.isCaptured() ? cvarUpperBound(v.bound) : v;
+        }
+        else return t;
+    }
+
     /**
      * Get a wildcard's lower bound, returning non-wildcards unchanged.
      * @param t a type argument, either a wildcard or a type
@@ -160,9 +157,7 @@
         }
         else return t;
     }
-    // </editor-fold>
-
-    // <editor-fold defaultstate="collapsed" desc="cvarLowerBound">
+
     /**
      * Get a capture variable's lower bound, returning other types unchanged.
      * @param t a type
@@ -894,7 +889,7 @@
                                              s.getAnnotationMirrors());
                         changed = true;
                     } else if (s != orig) {
-                        s = new WildcardType(upperBound(s),
+                        s = new WildcardType(wildUpperBound(s),
                                              BoundKind.EXTENDS,
                                              syms.boundClass,
                                              s.getAnnotationMirrors());
@@ -1104,7 +1099,7 @@
                         //check that u == t, where u has been set by Type.withTypeVar
                         return s.isSuperBound() &&
                                 !s.isExtendsBound() &&
-                                visit(t, upperBound(s));
+                                visit(t, wildUpperBound(s));
                     }
                 }
                 default:
@@ -1131,7 +1126,7 @@
                     return visit(s, t);
 
                 if (s.isSuperBound() && !s.isExtendsBound())
-                    return visit(t, upperBound(s)) && visit(t, wildLowerBound(s));
+                    return visit(t, wildUpperBound(s)) && visit(t, wildLowerBound(s));
 
                 if (t.isCompound() && s.isCompound()) {
                     if (!visit(supertype(t), supertype(s)))
@@ -1298,7 +1293,7 @@
                 switch(wt.kind) {
                     case UNBOUND: //similar to ? extends Object
                     case EXTENDS: {
-                        Type bound = upperBound(s);
+                        Type bound = wildUpperBound(s);
                         undetvar.addBound(InferenceBound.UPPER, bound, this);
                         break;
                     }
@@ -1359,28 +1354,6 @@
     // where
         private TypeRelation containsType = new TypeRelation() {
 
-            private Type U(Type t) {
-                while (t.hasTag(WILDCARD)) {
-                    WildcardType w = (WildcardType)t;
-                    if (w.isSuperBound())
-                        return w.bound == null ? syms.objectType : w.bound.bound;
-                    else
-                        t = w.type;
-                }
-                return t;
-            }
-
-            private Type L(Type t) {
-                while (t.hasTag(WILDCARD)) {
-                    WildcardType w = (WildcardType)t;
-                    if (w.isExtendsBound())
-                        return syms.botType;
-                    else
-                        t = w.type;
-                }
-                return t;
-            }
-
             public Boolean visitType(Type t, Type s) {
                 if (s.isPartial())
                     return containedBy(s, t);
@@ -1392,13 +1365,13 @@
 //                System.err.println();
 //                System.err.format(" does %s contain %s?%n", t, s);
 //                System.err.format(" %s U(%s) <: U(%s) %s = %s%n",
-//                                  upperBound(s), s, t, U(t),
+//                                  wildUpperBound(s), s, t, wildUpperBound(t),
 //                                  t.isSuperBound()
-//                                  || isSubtypeNoCapture(upperBound(s), U(t)));
+//                                  || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t)));
 //                System.err.format(" %s L(%s) <: L(%s) %s = %s%n",
-//                                  L(t), t, s, wildLowerBound(s),
+//                                  wildLowerBound(t), t, s, wildLowerBound(s),
 //                                  t.isExtendsBound()
-//                                  || isSubtypeNoCapture(L(t), wildLowerBound(s)));
+//                                  || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s)));
 //                System.err.println();
 //            }
 
@@ -1410,8 +1383,9 @@
 //                    debugContainsType(t, s);
                     return isSameWildcard(t, s)
                         || isCaptureOf(s, t)
-                        || ((t.isExtendsBound() || isSubtypeNoCapture(L(t), wildLowerBound(s))) &&
-                            (t.isSuperBound() || isSubtypeNoCapture(upperBound(s), U(t))));
+                        || ((t.isExtendsBound() || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s))) &&
+                            // TODO: JDK-8039214, cvarUpperBound call here is incorrect
+                            (t.isSuperBound() || isSubtypeNoCapture(cvarUpperBound(wildUpperBound(s)), wildUpperBound(t))));
                 }
             }
 
@@ -1529,7 +1503,7 @@
 
             @Override
             public Boolean visitWildcardType(WildcardType t, Type s) {
-                return isCastable(upperBound(t), s, warnStack.head);
+                return isCastable(wildUpperBound(t), s, warnStack.head);
             }
 
             @Override
@@ -1770,12 +1744,12 @@
 
                 if (t.isExtendsBound()) {
                     if (s.isExtendsBound())
-                        return !isCastableRecursive(t.type, upperBound(s));
+                        return !isCastableRecursive(t.type, wildUpperBound(s));
                     else if (s.isSuperBound())
                         return notSoftSubtypeRecursive(wildLowerBound(s), t.type);
                 } else if (t.isSuperBound()) {
                     if (s.isExtendsBound())
-                        return notSoftSubtypeRecursive(t.type, upperBound(s));
+                        return notSoftSubtypeRecursive(t.type, wildUpperBound(s));
                 }
                 return false;
             }
@@ -1811,7 +1785,7 @@
                                noWarnings);
         }
         if (!s.hasTag(WILDCARD))
-            s = upperBound(s);
+            s = cvarUpperBound(s);
 
         return !isSubtype(t, relaxBound(s));
     }
@@ -1868,7 +1842,7 @@
     // <editor-fold defaultstate="collapsed" desc="Array Utils">
     public boolean isArray(Type t) {
         while (t.hasTag(WILDCARD))
-            t = upperBound(t);
+            t = wildUpperBound(t);
         return t.hasTag(ARRAY);
     }
 
@@ -1878,7 +1852,7 @@
     public Type elemtype(Type t) {
         switch (t.getTag()) {
         case WILDCARD:
-            return elemtype(upperBound(t));
+            return elemtype(wildUpperBound(t));
         case ARRAY:
             return ((ArrayType)t).elemtype;
         case FORALL:
@@ -2080,7 +2054,7 @@
 
             @Override
             public Type visitWildcardType(WildcardType t, Symbol sym) {
-                return memberType(upperBound(t), sym);
+                return memberType(wildUpperBound(t), sym);
             }
 
             @Override
@@ -2208,7 +2182,7 @@
             @Override
             public Type visitWildcardType(WildcardType t, Boolean recurse) {
                 final List<Attribute.TypeCompound> annos = t.getAnnotationMirrors();
-                Type erased = erasure(upperBound(t), recurse);
+                Type erased = erasure(wildUpperBound(t), recurse);
                 if (!annos.isEmpty()) {
                     erased = erased.annotatedType(annos);
                 }
@@ -2417,8 +2391,7 @@
                         if (t.hasErasedSupertypes()) {
                             t.interfaces_field = erasureRecursive(interfaces);
                         } else if (formals.nonEmpty()) {
-                            t.interfaces_field =
-                                upperBounds(subst(interfaces, formals, actuals));
+                            t.interfaces_field = subst(interfaces, formals, actuals);
                         }
                         else {
                             t.interfaces_field = interfaces;
@@ -2987,7 +2960,7 @@
                                          t.getAnnotationMirrors());
             } else {
                 Type st = subst(supertype(t));
-                List<Type> is = upperBounds(subst(interfaces(t)));
+                List<Type> is = subst(interfaces(t));
                 if (st == supertype(t) && is == interfaces(t))
                     return t;
                 else
@@ -3004,7 +2977,7 @@
                 return t;
             } else {
                 if (t.isExtendsBound() && bound.isExtendsBound())
-                    bound = upperBound(bound);
+                    bound = wildUpperBound(bound);
                 return new WildcardType(bound, t.kind, syms.boundClass,
                                         t.bound, t.getAnnotationMirrors());
             }
@@ -3458,8 +3431,8 @@
                     TypePair pair = new TypePair(c1, c2);
                     Type m;
                     if (mergeCache.add(pair)) {
-                        m = new WildcardType(lub(upperBound(act1.head),
-                                                 upperBound(act2.head)),
+                        m = new WildcardType(lub(wildUpperBound(act1.head),
+                                                 wildUpperBound(act2.head)),
                                              BoundKind.EXTENDS,
                                              syms.boundClass,
                                              Type.noAnnotations);
@@ -4041,16 +4014,6 @@
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Internal utility methods">
-    private List<Type> upperBounds(List<Type> ss) {
-        if (ss.isEmpty()) return ss;
-        Type head = upperBound(ss.head);
-        List<Type> tail = upperBounds(ss.tail);
-        if (head != ss.head || tail != ss.tail)
-            return tail.prepend(head);
-        else
-            return ss;
-    }
-
     private boolean sideCast(Type from, Type to, Warner warn) {
         // We are casting from type $from$ to type $to$, which are
         // non-final unrelated types.  This method
@@ -4207,7 +4170,7 @@
         @Override
         public Void visitWildcardType(WildcardType source, Type target) throws AdaptFailure {
             if (source.isExtendsBound())
-                adaptRecursive(upperBound(source), upperBound(target));
+                adaptRecursive(wildUpperBound(source), wildUpperBound(target));
             else if (source.isSuperBound())
                 adaptRecursive(wildLowerBound(source), wildLowerBound(target));
             return null;
@@ -4224,7 +4187,7 @@
                     val = isSubtype(wildLowerBound(val), wildLowerBound(target))
                         ? target : val;
                 } else if (val.isExtendsBound() && target.isExtendsBound()) {
-                    val = isSubtype(upperBound(val), upperBound(target))
+                    val = isSubtype(wildUpperBound(val), wildUpperBound(target))
                         ? val : target;
                 } else if (!isSameType(val, target)) {
                     throw new AdaptFailure();
@@ -4335,7 +4298,7 @@
         }
 
         public Type visitType(Type t, Void s) {
-            return high ? upperBound(t) : t;
+            return t;
         }
 
         @Override
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue May 27 14:23:55 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue May 27 16:32:56 2014 -0600
@@ -1176,7 +1176,7 @@
             //the Formal Parameter of a for-each loop is not in the scope when
             //attributing the for-each expression; we mimick this by attributing
             //the for-each expression first (against original scope).
-            Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv));
+            Type exprType = types.cvarUpperBound(attribExpr(tree.expr, loopEnv));
             attribStat(tree.var, loopEnv);
             chk.checkNonVoid(tree.pos(), exprType);
             Type elemtype = types.elemtype(exprType); // perhaps expr is an array?
@@ -1193,7 +1193,7 @@
                     List<Type> iterableParams = base.allparams();
                     elemtype = iterableParams.isEmpty()
                         ? syms.objectType
-                        : types.upperBound(iterableParams.head);
+                        : types.wildUpperBound(iterableParams.head);
                 }
             }
             chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Tue May 27 14:23:55 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Tue May 27 16:32:56 2014 -0600
@@ -621,10 +621,10 @@
          if (a.isUnbound()) {
              return true;
          } else if (!a.hasTag(WILDCARD)) {
-             a = types.upperBound(a);
+             a = types.cvarUpperBound(a);
              return types.isSubtype(a, bound);
          } else if (a.isExtendsBound()) {
-             return types.isCastable(bound, types.upperBound(a), types.noWarnings);
+             return types.isCastable(bound, types.wildUpperBound(a), types.noWarnings);
          } else if (a.isSuperBound()) {
              return !types.notSoftSubtype(types.wildLowerBound(a), bound);
          }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Tue May 27 14:23:55 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Tue May 27 16:32:56 2014 -0600
@@ -3522,7 +3522,7 @@
         private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
             make_at(tree.expr.pos());
             Type iteratorTarget = syms.objectType;
-            Type iterableType = types.asSuper(types.upperBound(tree.expr.type),
+            Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type),
                                               syms.iterableType.tsym);
             if (iterableType.getTypeArguments().nonEmpty())
                 iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
@@ -3556,7 +3556,7 @@
                                        List.<Type>nil());
             JCExpression vardefinit = make.App(make.Select(make.Ident(itvar), next));
             if (tree.var.type.isPrimitive())
-                vardefinit = make.TypeCast(types.upperBound(iteratorTarget), vardefinit);
+                vardefinit = make.TypeCast(types.cvarUpperBound(iteratorTarget), vardefinit);
             else
                 vardefinit = make.TypeCast(tree.var.type, vardefinit);
             JCVariableDecl indexDef = (JCVariableDecl)make.VarDef(tree.var.mods,
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue May 27 14:23:55 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue May 27 16:32:56 2014 -0600
@@ -347,7 +347,7 @@
 
     boolean isAccessible(Env<AttrContext> env, Type t, boolean checkInner) {
         return (t.hasTag(ARRAY))
-            ? isAccessible(env, types.upperBound(types.elemtype(t)))
+            ? isAccessible(env, types.cvarUpperBound(types.elemtype(t)))
             : isAccessible(env, t.tsym, checkInner);
     }
 
@@ -1014,7 +1014,7 @@
          */
         private Type U(Type found) {
             return found == pt ?
-                    found : types.upperBound(found);
+                    found : types.cvarUpperBound(found);
         }
 
         @Override