langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
changeset 1527 815e743a83ba
parent 1358 a51c5f89f8af
child 1531 37df4e42719a
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Oct 20 13:42:45 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Oct 23 17:59:16 2008 +0100
@@ -424,43 +424,43 @@
      *  @param bs            The bound.
      */
     private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) {
-        if (a.tag == TYPEVAR && ((TypeVar)a).isCaptured()) {
-            CapturedType ct = (CapturedType)a;
-            boolean ok;
-            if (ct.bound.isErroneous()) {//capture doesn't exist
-                ok = false;
+         if (a.isUnbound()) {
+             return;
+         } else if (a.tag != WILDCARD) {
+             a = types.upperBound(a);
+             for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) {
+                 if (!types.isSubtype(a, l.head)) {
+                     log.error(pos, "not.within.bounds", a);
+                     return;
+                 }
+             }
+         } else if (a.isExtendsBound()) {
+             if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings))
+                 log.error(pos, "not.within.bounds", a);
+         } else if (a.isSuperBound()) {
+             if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound()))
+                 log.error(pos, "not.within.bounds", a);
+         }
+     }
+
+    /** Check that a type is within some bounds.
+     *
+     *  Used in TypeApply to verify that, e.g., X in V<X> is a valid
+     *  type argument.
+     *  @param pos           Position to be used for error reporting.
+     *  @param a             The type that should be bounded by bs.
+     *  @param bs            The bound.
+     */
+    private void checkCapture(JCTypeApply tree) {
+        List<JCExpression> args = tree.getTypeArguments();
+        for (Type arg : types.capture(tree.type).getTypeArguments()) {
+            if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) {
+                log.error(args.head.pos, "not.within.bounds", args.head.type);
+                break;
             }
-            else {
-                switch (ct.wildcard.kind) {
-                    case EXTENDS:
-                        ok = types.isCastable(bs.getUpperBound(),
-                                types.upperBound(a),
-                                Warner.noWarnings);
-                        break;
-                    case SUPER:
-                        ok = !types.notSoftSubtype(types.lowerBound(a),
-                                bs.getUpperBound());
-                        break;
-                    case UNBOUND:
-                        ok = true;
-                        break;
-                    default:
-                        throw new AssertionError("Invalid bound kind");
-                }
-            }
-            if (!ok)
-                log.error(pos, "not.within.bounds", a);
+            args = args.tail;
         }
-        else {
-            a = types.upperBound(a);
-            for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) {
-                if (!types.isSubtype(a, l.head)) {
-                    log.error(pos, "not.within.bounds", a);
-                    return;
-                }
-            }
-        }
-    }
+     }
 
     /** Check that type is different from 'void'.
      *  @param pos           Position to be used for error reporting.
@@ -803,7 +803,7 @@
         public void visitTypeApply(JCTypeApply tree) {
             if (tree.type.tag == CLASS) {
                 List<Type> formals = tree.type.tsym.type.getTypeArguments();
-                List<Type> actuals = types.capture(tree.type).getTypeArguments();
+                List<Type> actuals = tree.type.getTypeArguments();
                 List<JCExpression> args = tree.arguments;
                 List<Type> forms = formals;
                 ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>();
@@ -826,24 +826,28 @@
                 }
 
                 args = tree.arguments;
+                List<Type> tvars_cap = types.substBounds(formals,
+                                          formals,
+                                          types.capture(tree.type).getTypeArguments());
+                while (args.nonEmpty() && tvars_cap.nonEmpty()) {
+                    // Let the actual arguments know their bound
+                    args.head.type.withTypeVar((TypeVar)tvars_cap.head);
+                    args = args.tail;
+                    tvars_cap = tvars_cap.tail;
+                }
+
+                args = tree.arguments;
                 List<TypeVar> tvars = tvars_buf.toList();
+
                 while (args.nonEmpty() && tvars.nonEmpty()) {
-                    // Let the actual arguments know their bound
-                    args.head.type.withTypeVar(tvars.head);
+                    checkExtends(args.head.pos(),
+                                 args.head.type,
+                                 tvars.head);
                     args = args.tail;
                     tvars = tvars.tail;
                 }
 
-                args = tree.arguments;
-                tvars = tvars_buf.toList();
-                while (args.nonEmpty() && tvars.nonEmpty()) {
-                    checkExtends(args.head.pos(),
-                                 actuals.head,
-                                 tvars.head);
-                    args = args.tail;
-                    tvars = tvars.tail;
-                    actuals = actuals.tail;
-                }
+                checkCapture(tree);
 
                 // Check that this type is either fully parameterized, or
                 // not parameterized at all.