langtools/src/share/classes/com/sun/tools/javac/code/Types.java
changeset 24293 0d889f759fac
parent 24291 440746208be7
child 24396 3c36c6afcbca
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Fri May 02 16:41:10 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Tue May 06 15:46:09 2014 -0600
@@ -151,31 +151,31 @@
         };
     // </editor-fold>
 
-    // <editor-fold defaultstate="collapsed" desc="lowerBound">
+    // <editor-fold defaultstate="collapsed" desc="wildLowerBound">
     /**
-     * The "lvalue conversion".<br>
-     * The lower bound of most types is the type
-     * itself.  Wildcards, on the other hand have upper
-     * and lower bounds.
-     * @param t a type
-     * @return the lower bound of the given type
+     * Get a wildcard's lower bound, returning non-wildcards unchanged.
+     * @param t a type argument, either a wildcard or a type
      */
-    public Type lowerBound(Type t) {
-        return lowerBound.visit(t);
+    public Type wildLowerBound(Type t) {
+        if (t.hasTag(WILDCARD)) {
+            WildcardType w = (WildcardType) t;
+            return w.isExtendsBound() ? syms.botType : wildLowerBound(w.type);
+        }
+        else return t;
     }
-    // where
-        private final MapVisitor<Void> lowerBound = new MapVisitor<Void>() {
-
-            @Override
-            public Type visitWildcardType(WildcardType t, Void ignored) {
-                return t.isExtendsBound() ? syms.botType : visit(t.type);
-            }
-
-            @Override
-            public Type visitCapturedType(CapturedType t, Void ignored) {
-                return visit(t.getLowerBound());
-            }
-        };
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="cvarLowerBound">
+    /**
+     * Get a capture variable's lower bound, returning other types unchanged.
+     * @param t a type
+     */
+    public Type cvarLowerBound(Type t) {
+        if (t.hasTag(TYPEVAR) && ((TypeVar) t).isCaptured()) {
+            return cvarLowerBound(t.getLowerBound());
+        }
+        else return t;
+    }
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="isUnbounded">
@@ -827,9 +827,14 @@
             return true;
         }
 
-        Type lower = lowerBound(s);
-        if (s != lower)
-            return isSubtype(capture ? capture(t) : t, lower, false);
+        // Generally, if 's' is a type variable, recur on lower bound; but
+        // for alpha <: CAP, alpha should get upper bound CAP
+        if (!t.hasTag(UNDETVAR)) {
+            // TODO: JDK-8039198, bounds checking sometimes passes in a wildcard as s
+            Type lower = cvarLowerBound(wildLowerBound(s));
+            if (s != lower)
+                return isSubtype(capture ? capture(t) : t, lower, false);
+        }
 
         return isSubtype.visit(capture ? capture(t) : t, s);
     }
@@ -1136,7 +1141,7 @@
                     return visit(s, t);
 
                 if (s.isSuperBound() && !s.isExtendsBound())
-                    return visit(t, upperBound(s)) && visit(t, lowerBound(s));
+                    return visit(t, upperBound(s)) && visit(t, wildLowerBound(s));
 
                 if (t.isCompound() && s.isCompound()) {
                     if (!visit(supertype(t), supertype(s)))
@@ -1291,7 +1296,7 @@
                         break;
                     }
                     case SUPER: {
-                        Type bound = lowerBound(s);
+                        Type bound = wildLowerBound(s);
                         undetvar.addBound(InferenceBound.LOWER, bound, this);
                         break;
                     }
@@ -1384,9 +1389,9 @@
 //                                  t.isSuperBound()
 //                                  || isSubtypeNoCapture(upperBound(s), U(t)));
 //                System.err.format(" %s L(%s) <: L(%s) %s = %s%n",
-//                                  L(t), t, s, lowerBound(s),
+//                                  L(t), t, s, wildLowerBound(s),
 //                                  t.isExtendsBound()
-//                                  || isSubtypeNoCapture(L(t), lowerBound(s)));
+//                                  || isSubtypeNoCapture(L(t), wildLowerBound(s)));
 //                System.err.println();
 //            }
 
@@ -1398,7 +1403,7 @@
 //                    debugContainsType(t, s);
                     return isSameWildcard(t, s)
                         || isCaptureOf(s, t)
-                        || ((t.isExtendsBound() || isSubtypeNoCapture(L(t), lowerBound(s))) &&
+                        || ((t.isExtendsBound() || isSubtypeNoCapture(L(t), wildLowerBound(s))) &&
                             (t.isSuperBound() || isSubtypeNoCapture(upperBound(s), U(t))));
                 }
             }
@@ -1760,7 +1765,7 @@
                     if (s.isExtendsBound())
                         return !isCastableRecursive(t.type, upperBound(s));
                     else if (s.isSuperBound())
-                        return notSoftSubtypeRecursive(lowerBound(s), t.type);
+                        return notSoftSubtypeRecursive(wildLowerBound(s), t.type);
                 } else if (t.isSuperBound()) {
                     if (s.isExtendsBound())
                         return notSoftSubtypeRecursive(t.type, upperBound(s));
@@ -1770,19 +1775,13 @@
         };
     // </editor-fold>
 
-    // <editor-fold defaultstate="collapsed" desc="lowerBoundArgtypes">
-    /**
-     * Returns the lower bounds of the formals of a method.
-     */
-    public List<Type> lowerBoundArgtypes(Type t) {
-        return lowerBounds(t.getParameterTypes());
+    // <editor-fold defaultstate="collapsed" desc="cvarLowerBounds">
+    public List<Type> cvarLowerBounds(List<Type> ts) {
+        return map(ts, cvarLowerBoundMapping);
     }
-    public List<Type> lowerBounds(List<Type> ts) {
-        return map(ts, lowerBoundMapping);
-    }
-    private final Mapping lowerBoundMapping = new Mapping("lowerBound") {
+    private final Mapping cvarLowerBoundMapping = new Mapping("cvarLowerBound") {
             public Type apply(Type t) {
-                return lowerBound(t);
+                return cvarLowerBound(t);
             }
         };
     // </editor-fold>
@@ -2251,7 +2250,8 @@
 
     // <editor-fold defaultstate="collapsed" desc="makeCompoundType">
     /**
-     * Make a compound type from non-empty list of types
+     * Make a compound type from non-empty list of types.  The list should be
+     * ordered according to {@link Symbol#precedes(TypeSymbol,Types)}.
      *
      * @param bounds            the types from which the compound type is formed
      * @param supertype         is objectType if all bounds are interfaces,
@@ -3340,12 +3340,15 @@
      * Insert a type in a closure
      */
     public List<Type> insert(List<Type> cl, Type t) {
-        if (cl.isEmpty() || t.tsym.precedes(cl.head.tsym, this)) {
+        if (cl.isEmpty()) {
             return cl.prepend(t);
-        } else if (cl.head.tsym.precedes(t.tsym, this)) {
+        } else if (t.tsym == cl.head.tsym) {
+            return cl;
+        } else if (t.tsym.precedes(cl.head.tsym, this)) {
+            return cl.prepend(t);
+        } else {
+            // t comes after head, or the two are unrelated
             return insert(cl.tail, t).prepend(cl.head);
-        } else {
-            return cl;
         }
     }
 
@@ -3357,12 +3360,15 @@
             return cl2;
         } else if (cl2.isEmpty()) {
             return cl1;
+        } else if (cl1.head.tsym == cl2.head.tsym) {
+            return union(cl1.tail, cl2.tail).prepend(cl1.head);
         } else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) {
             return union(cl1.tail, cl2).prepend(cl1.head);
         } else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) {
             return union(cl1, cl2.tail).prepend(cl2.head);
         } else {
-            return union(cl1.tail, cl2.tail).prepend(cl1.head);
+            // unrelated types
+            return union(cl1.tail, cl2).prepend(cl1.head);
         }
     }
 
@@ -3472,18 +3478,31 @@
     private List<Type> closureMin(List<Type> cl) {
         ListBuffer<Type> classes = new ListBuffer<>();
         ListBuffer<Type> interfaces = new ListBuffer<>();
+        Set<Type> toSkip = new HashSet<>();
         while (!cl.isEmpty()) {
             Type current = cl.head;
-            if (current.isInterface())
-                interfaces.append(current);
-            else
-                classes.append(current);
-            ListBuffer<Type> candidates = new ListBuffer<>();
-            for (Type t : cl.tail) {
-                if (!isSubtypeNoCapture(current, t))
-                    candidates.append(t);
+            boolean keep = !toSkip.contains(current);
+            if (keep && current.hasTag(TYPEVAR)) {
+                // skip lower-bounded variables with a subtype in cl.tail
+                for (Type t : cl.tail) {
+                    if (isSubtypeNoCapture(t, current)) {
+                        keep = false;
+                        break;
+                    }
+                }
             }
-            cl = candidates.toList();
+            if (keep) {
+                if (current.isInterface())
+                    interfaces.append(current);
+                else
+                    classes.append(current);
+                for (Type t : cl.tail) {
+                    // skip supertypes of 'current' in cl.tail
+                    if (isSubtypeNoCapture(current, t))
+                        toSkip.add(t);
+                }
+            }
+            cl = cl.tail;
         }
         return classes.appendList(interfaces).toList();
     }
@@ -3643,7 +3662,19 @@
             return s;
 
         List<Type> closure = union(closure(t), closure(s));
-        List<Type> bounds = closureMin(closure);
+        return glbFlattened(closure, t);
+    }
+    //where
+    /**
+     * Perform glb for a list of non-primitive, non-error, non-compound types;
+     * redundant elements are removed.  Bounds should be ordered according to
+     * {@link Symbol#precedes(TypeSymbol,Types)}.
+     *
+     * @param flatBounds List of type to glb
+     * @param errT Original type to use if the result is an error type
+     */
+    private Type glbFlattened(List<Type> flatBounds, Type errT) {
+        List<Type> bounds = closureMin(flatBounds);
 
         if (bounds.isEmpty()) {             // length == 0
             return syms.objectType;
@@ -3651,11 +3682,21 @@
             return bounds.head;
         } else {                            // length > 1
             int classCount = 0;
-            for (Type bound : bounds)
-                if (!bound.isInterface())
+            List<Type> lowers = List.nil();
+            for (Type bound : bounds) {
+                if (!bound.isInterface()) {
                     classCount++;
-            if (classCount > 1)
-                return createErrorType(t);
+                    Type lower = cvarLowerBound(bound);
+                    if (bound != lower && !lower.hasTag(BOT))
+                        lowers = insert(lowers, lower);
+                }
+            }
+            if (classCount > 1) {
+                if (lowers.isEmpty())
+                    return createErrorType(errT);
+                else
+                    return glbFlattened(union(bounds, lowers), errT);
+            }
         }
         return makeCompoundType(bounds);
     }
@@ -4140,7 +4181,7 @@
             if (source.isExtendsBound())
                 adaptRecursive(upperBound(source), upperBound(target));
             else if (source.isSuperBound())
-                adaptRecursive(lowerBound(source), lowerBound(target));
+                adaptRecursive(wildLowerBound(source), wildLowerBound(target));
             return null;
         }
 
@@ -4152,7 +4193,7 @@
             Type val = mapping.get(source.tsym);
             if (val != null) {
                 if (val.isSuperBound() && target.isSuperBound()) {
-                    val = isSubtype(lowerBound(val), lowerBound(target))
+                    val = isSubtype(wildLowerBound(val), wildLowerBound(target))
                         ? target : val;
                 } else if (val.isExtendsBound() && target.isExtendsBound()) {
                     val = isSubtype(upperBound(val), upperBound(target))
@@ -4266,7 +4307,7 @@
         }
 
         public Type visitType(Type t, Void s) {
-            return high ? upperBound(t) : lowerBound(t);
+            return high ? upperBound(t) : t;
         }
 
         @Override