langtools/src/share/classes/com/sun/tools/javac/code/Types.java
changeset 6353 bb5c39054bf3
parent 6350 7070b0722ebb
child 6575 ae1798028008
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Aug 19 11:54:25 2010 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Mon Aug 23 16:59:30 2010 +0100
@@ -960,7 +960,7 @@
                     return true;
 
                 if (s.tag == TYPEVAR) {
-                    if (isCastable(s.getUpperBound(), t, Warner.noWarnings)) {
+                    if (isCastable(t, s.getUpperBound(), Warner.noWarnings)) {
                         warnStack.head.warnUnchecked();
                         return true;
                     } else {
@@ -1030,7 +1030,12 @@
                                 && !disjointTypes(aHigh.allparams(), lowSub.allparams())
                                 && !disjointTypes(aLow.allparams(), highSub.allparams())
                                 && !disjointTypes(aLow.allparams(), lowSub.allparams())) {
-                                if (upcast ? giveWarning(a, b) :
+                                if (s.isInterface() &&
+                                        !t.isInterface() &&
+                                        t.isFinal() &&
+                                        !isSubtype(t, s)) {
+                                    return false;
+                                } else if (upcast ? giveWarning(a, b) :
                                     giveWarning(b, a))
                                     warnStack.head.warnUnchecked();
                                 return true;
@@ -1230,18 +1235,23 @@
         if (t == s) return false;
         if (t.tag == TYPEVAR) {
             TypeVar tv = (TypeVar) t;
-            if (s.tag == TYPEVAR)
-                s = s.getUpperBound();
             return !isCastable(tv.bound,
-                               s,
+                               relaxBound(s),
                                Warner.noWarnings);
         }
         if (s.tag != WILDCARD)
             s = upperBound(s);
-        if (s.tag == TYPEVAR)
-            s = s.getUpperBound();
-
-        return !isSubtype(t, s);
+
+        return !isSubtype(t, relaxBound(s));
+    }
+
+    private Type relaxBound(Type t) {
+        if (t.tag == TYPEVAR) {
+            while (t.tag == TYPEVAR)
+                t = t.getUpperBound();
+            t = rewriteQuantifiers(t, true, true);
+        }
+        return t;
     }
     // </editor-fold>
 
@@ -3280,7 +3290,7 @@
      * quantifiers) only
      */
     private Type rewriteQuantifiers(Type t, boolean high, boolean rewriteTypeVars) {
-        return new Rewriter(high, rewriteTypeVars).rewrite(t);
+        return new Rewriter(high, rewriteTypeVars).visit(t);
     }
 
     class Rewriter extends UnaryVisitor<Type> {
@@ -3293,25 +3303,21 @@
             this.rewriteTypeVars = rewriteTypeVars;
         }
 
-        Type rewrite(Type t) {
-            ListBuffer<Type> from = new ListBuffer<Type>();
-            ListBuffer<Type> to = new ListBuffer<Type>();
-            adaptSelf(t, from, to);
+        @Override
+        public Type visitClassType(ClassType t, Void s) {
             ListBuffer<Type> rewritten = new ListBuffer<Type>();
-            List<Type> formals = from.toList();
             boolean changed = false;
-            for (Type arg : to.toList()) {
+            for (Type arg : t.allparams()) {
                 Type bound = visit(arg);
                 if (arg != bound) {
                     changed = true;
-                    bound = high ? makeExtendsWildcard(bound, (TypeVar)formals.head)
-                              : makeSuperWildcard(bound, (TypeVar)formals.head);
                 }
                 rewritten.append(bound);
-                formals = formals.tail;
             }
             if (changed)
-                return subst(t.tsym.type, from.toList(), rewritten.toList());
+                return subst(t.tsym.type,
+                        t.tsym.type.allparams(),
+                        rewritten.toList());
             else
                 return t;
         }
@@ -3322,13 +3328,22 @@
 
         @Override
         public Type visitCapturedType(CapturedType t, Void s) {
-            return visitWildcardType(t.wildcard, null);
+            Type bound = visitWildcardType(t.wildcard, null);
+            return (bound.contains(t)) ?
+                    (high ? syms.objectType : syms.botType) :
+                        bound;
         }
 
         @Override
         public Type visitTypeVar(TypeVar t, Void s) {
-            if (rewriteTypeVars)
-                return high ? t.bound : syms.botType;
+            if (rewriteTypeVars) {
+                Type bound = high ?
+                    (t.bound.contains(t) ?
+                        syms.objectType :
+                        visit(t.bound)) :
+                    syms.botType;
+                return rewriteAsWildcardType(bound, t);
+            }
             else
                 return t;
         }
@@ -3338,11 +3353,31 @@
             Type bound = high ? t.getExtendsBound() :
                                 t.getSuperBound();
             if (bound == null)
-                bound = high ? syms.objectType : syms.botType;
-            return bound;
+            bound = high ? syms.objectType : syms.botType;
+            return rewriteAsWildcardType(visit(bound), t.bound);
+        }
+
+        private Type rewriteAsWildcardType(Type bound, TypeVar formal) {
+            return high ?
+                makeExtendsWildcard(B(bound), formal) :
+                makeSuperWildcard(B(bound), formal);
+        }
+
+        Type B(Type t) {
+            while (t.tag == WILDCARD) {
+                WildcardType w = (WildcardType)t;
+                t = high ?
+                    w.getExtendsBound() :
+                    w.getSuperBound();
+                if (t == null) {
+                    t = high ? syms.objectType : syms.botType;
+                }
+            }
+            return t;
         }
     }
 
+
     /**
      * Create a wildcard with the given upper (extends) bound; create
      * an unbounded wildcard if bound is Object.