6943278: spurious error message for inference and type-variable with erroneous bound
authormcimadamore
Mon, 24 Jan 2011 15:44:15 +0000
changeset 8044 7fd529d4472c
parent 8043 c19058ce05e8
child 8045 df2ca0edfbaa
6943278: spurious error message for inference and type-variable with erroneous bound Summary: type-inference should ignore erroneous bounds 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/src/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/test/tools/javac/generics/inference/6943278/T6943278.java
langtools/test/tools/javac/generics/inference/6943278/T6943278.out
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Wed Jan 19 19:01:35 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Mon Jan 24 15:44:15 2011 +0000
@@ -365,6 +365,16 @@
         return false;
     }
 
+    public static List<Type> filter(List<Type> ts, Filter<Type> tf) {
+        ListBuffer<Type> buf = ListBuffer.lb();
+        for (Type t : ts) {
+            if (tf.accepts(t)) {
+                buf.append(t);
+            }
+        }
+        return buf.toList();
+    }
+
     public boolean isSuperBound() { return false; }
     public boolean isExtendsBound() { return false; }
     public boolean isUnbound() { return false; }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Wed Jan 19 19:01:35 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Jan 24 15:44:15 2011 +0000
@@ -800,7 +800,8 @@
                 Type actual = types.subst(args.head,
                     type.tsym.type.getTypeArguments(),
                     tvars_buf.toList());
-                if (!checkExtends(actual, (TypeVar)tvars.head)) {
+                if (!checkExtends(actual, (TypeVar)tvars.head) &&
+                        !tvars.head.getUpperBound().isErroneous()) {
                     return args.head;
                 }
                 args = args.tail;
@@ -808,11 +809,15 @@
             }
 
             args = type.getTypeArguments();
+            tvars = tvars_buf.toList();
 
             for (Type arg : types.capture(type).getTypeArguments()) {
-                if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) {
+                if (arg.tag == TYPEVAR &&
+                        arg.getUpperBound().isErroneous() &&
+                        !tvars.head.getUpperBound().isErroneous()) {
                     return args.head;
                 }
+                tvars = tvars.tail;
             }
 
             return null;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jan 19 19:01:35 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Jan 24 15:44:15 2011 +0000
@@ -205,19 +205,20 @@
      *  Throw a NoInstanceException if this not possible.
      */
     void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException {
+        List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
         if (that.inst == null) {
-            if (that.hibounds.isEmpty())
+            if (hibounds.isEmpty())
                 that.inst = syms.objectType;
-            else if (that.hibounds.tail.isEmpty())
-                that.inst = that.hibounds.head;
+            else if (hibounds.tail.isEmpty())
+                that.inst = hibounds.head;
             else
-                that.inst = types.glb(that.hibounds);
+                that.inst = types.glb(hibounds);
         }
         if (that.inst == null ||
             that.inst.isErroneous())
             throw ambiguousNoInstanceException
                 .setMessage("no.unique.maximal.instance.exists",
-                            that.qtype, that.hibounds);
+                            that.qtype, hibounds);
     }
     //where
         private boolean isSubClass(Type t, final List<Type> ts) {
@@ -241,37 +242,46 @@
             return true;
         }
 
+    private Filter<Type> errorFilter = new Filter<Type>() {
+        @Override
+        public boolean accepts(Type t) {
+            return !t.isErroneous();
+        }
+    };
+
     /** Instantiate undetermined type variable to the lub of all its lower bounds.
      *  Throw a NoInstanceException if this not possible.
      */
     void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException {
+        List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
         if (that.inst == null) {
-            if (that.lobounds.isEmpty())
+            if (lobounds.isEmpty())
                 that.inst = syms.botType;
-            else if (that.lobounds.tail.isEmpty())
-                that.inst = that.lobounds.head.isPrimitive() ? syms.errType : that.lobounds.head;
+            else if (lobounds.tail.isEmpty())
+                that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
             else {
-                that.inst = types.lub(that.lobounds);
+                that.inst = types.lub(lobounds);
             }
             if (that.inst == null || that.inst.tag == ERROR)
                     throw ambiguousNoInstanceException
                         .setMessage("no.unique.minimal.instance.exists",
-                                    that.qtype, that.lobounds);
+                                    that.qtype, lobounds);
             // VGJ: sort of inlined maximizeInst() below.  Adding
             // bounds can cause lobounds that are above hibounds.
-            if (that.hibounds.isEmpty())
+            List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
+            if (hibounds.isEmpty())
                 return;
             Type hb = null;
-            if (that.hibounds.tail.isEmpty())
-                hb = that.hibounds.head;
-            else for (List<Type> bs = that.hibounds;
+            if (hibounds.tail.isEmpty())
+                hb = hibounds.head;
+            else for (List<Type> bs = hibounds;
                       bs.nonEmpty() && hb == null;
                       bs = bs.tail) {
-                if (isSubClass(bs.head, that.hibounds))
+                if (isSubClass(bs.head, hibounds))
                     hb = types.fromUnknownFun.apply(bs.head);
             }
             if (hb == null ||
-                !types.isSubtypeUnchecked(hb, that.hibounds, warn) ||
+                !types.isSubtypeUnchecked(hb, hibounds, warn) ||
                 !types.isSubtypeUnchecked(that.inst, hb, warn))
                 throw ambiguousNoInstanceException;
         }
@@ -528,7 +538,8 @@
         for (List<Type> tvs = tvars, args = arguments;
              tvs.nonEmpty();
              tvs = tvs.tail, args = args.tail) {
-            if (args.head instanceof UndetVar) continue;
+            if (args.head instanceof UndetVar ||
+                    tvars.head.getUpperBound().isErroneous()) continue;
             List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments);
             if (!types.isSubtypeUnchecked(args.head, bounds, warn))
                 throw invalidInstanceException
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/6943278/T6943278.java	Mon Jan 24 15:44:15 2011 +0000
@@ -0,0 +1,12 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 6943278
+ * @summary spurious error message for inference and type-variable with erroneous bound
+ * @compile/fail/ref=T6943278.out -XDrawDiagnostics -Xlint:unchecked T6943278.java
+ */
+class T6943278<X extends Number & NonExistentInterface> {
+    <X> T6943278<X> m() { return null;}
+    <X extends Number & NonExistentInterface> T6943278<X> m(X x) { return null;}
+    T6943278<?> f1 = m();
+    T6943278<?> f2 = m("");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/6943278/T6943278.out	Mon Jan 24 15:44:15 2011 +0000
@@ -0,0 +1,3 @@
+T6943278.java:7:35: compiler.err.cant.resolve: kindname.class, NonExistentInterface, , 
+T6943278.java:9:25: compiler.err.cant.resolve.location: kindname.class, NonExistentInterface, , , kindname.class, T6943278<X>
+2 errors