6732484: Bound error on wildcard code
authormcimadamore
Thu, 23 Oct 2008 17:59:16 +0100
changeset 1527 815e743a83ba
parent 1486 a7d1338ca96e
child 1528 441d4ec466de
6732484: Bound error on wildcard code Summary: Check.checkExtends should cope with captured type-variables Reviewed-by: jjg
langtools/src/share/classes/com/sun/tools/javac/code/Type.java
langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
langtools/test/tools/javac/generics/wildcards/T6732484.java
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Mon Oct 20 13:42:45 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Thu Oct 23 17:59:16 2008 +0100
@@ -360,17 +360,6 @@
     public boolean isUnbound() { return false; }
     public Type withTypeVar(Type t) { return this; }
 
-    public static List<Type> removeBounds(List<Type> ts) {
-        ListBuffer<Type> result = new ListBuffer<Type>();
-        for(;ts.nonEmpty(); ts = ts.tail) {
-            result.append(ts.head.removeBounds());
-        }
-        return result.toList();
-    }
-    public Type removeBounds() {
-        return this;
-    }
-
     /** The underlying method type of this type.
      */
     public MethodType asMethodType() { throw new AssertionError(); }
@@ -489,10 +478,6 @@
                 return new WildcardType(t, kind, tsym, bound);
         }
 
-        public Type removeBounds() {
-            return isUnbound() ? this : type;
-        }
-
         public Type getExtendsBound() {
             if (kind == EXTENDS)
                 return type;
--- 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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/wildcards/T6732484.java	Thu Oct 23 17:59:16 2008 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6732484
+ * @summary Bound error on wildcard code
+ * @author Maurizio Cimadamore
+ * @compile T6732484.java
+ */
+
+class T6732484 {
+    class A<T extends A<T>> {}
+    class B extends A<B> {}
+
+    A<? super B> f;
+}
\ No newline at end of file