8019824: very long error messages on inference error
authormcimadamore
Fri, 05 Jul 2013 11:05:02 +0100
changeset 18904 3c4c6457ec5b
parent 18903 99f42bd11bc2
child 18905 e8f4a37b9376
8019824: very long error messages on inference error Summary: Inference error messages shows several spurious captured variables generated during an inference loop Reviewed-by: jjg, vromero
langtools/src/share/classes/com/sun/tools/javac/code/Type.java
langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/test/tools/javac/generics/inference/8019824/T8019824.java
langtools/test/tools/javac/generics/inference/8019824/T8019824.out
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Fri Jul 05 11:04:22 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Fri Jul 05 11:05:02 2013 +0100
@@ -1514,9 +1514,14 @@
             return buf.toList();
         }
 
+        /** internal method used to override an undetvar bounds */
+        public void setBounds(InferenceBound ib, List<Type> newBounds) {
+            bounds.put(ib, newBounds);
+        }
+
         /** add a bound of a given kind - this might trigger listener notification */
         public void addBound(InferenceBound ib, Type bound, Types types) {
-            Type bound2 = toTypeVarMap.apply(bound);
+            Type bound2 = boundMap.apply(bound);
             List<Type> prevBounds = bounds.get(ib);
             for (Type b : prevBounds) {
                 //check for redundancy - use strict version of isSameType on tvars
@@ -1527,12 +1532,12 @@
             notifyChange(EnumSet.of(ib));
         }
         //where
-            Type.Mapping toTypeVarMap = new Mapping("toTypeVarMap") {
+            Type.Mapping boundMap = new Mapping("boundMap") {
                 @Override
                 public Type apply(Type t) {
                     if (t.hasTag(UNDETVAR)) {
                         UndetVar uv = (UndetVar)t;
-                        return uv.qtype;
+                        return uv.inst != null ? uv.inst : uv.qtype;
                     } else {
                         return t.map(this);
                     }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Jul 05 11:04:22 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Jul 05 11:05:02 2013 +0100
@@ -418,6 +418,7 @@
     void checkWithinBounds(InferenceContext inferenceContext,
                              Warner warn) throws InferenceException {
         MultiUndetVarListener mlistener = new MultiUndetVarListener(inferenceContext.undetvars);
+        List<Type> saved_undet = inferenceContext.save();
         try {
             while (true) {
                 mlistener.reset();
@@ -443,6 +444,9 @@
         }
         finally {
             mlistener.detach();
+            if (mlistener.rounds == MAX_INCORPORATION_STEPS) {
+                inferenceContext.rollback(saved_undet);
+            }
         }
     }
     //where
@@ -645,7 +649,7 @@
                         UndetVar uv2 = (UndetVar)inferenceContext.asFree(b);
                         //alpha <: beta
                         //0. set beta :> alpha
-                        uv2.addBound(InferenceBound.LOWER, uv.qtype, infer.types);
+                        uv2.addBound(InferenceBound.LOWER, uv, infer.types);
                         //1. copy alpha's lower to beta's
                         for (Type l : uv.getBounds(InferenceBound.LOWER)) {
                             uv2.addBound(InferenceBound.LOWER, inferenceContext.asInstType(l), infer.types);
@@ -670,7 +674,7 @@
                         UndetVar uv2 = (UndetVar)inferenceContext.asFree(b);
                         //alpha :> beta
                         //0. set beta <: alpha
-                        uv2.addBound(InferenceBound.UPPER, uv.qtype, infer.types);
+                        uv2.addBound(InferenceBound.UPPER, uv, infer.types);
                         //1. copy alpha's upper to beta's
                         for (Type u : uv.getBounds(InferenceBound.UPPER)) {
                             uv2.addBound(InferenceBound.UPPER, inferenceContext.asInstType(u), infer.types);
@@ -695,7 +699,7 @@
                         UndetVar uv2 = (UndetVar)inferenceContext.asFree(b);
                         //alpha == beta
                         //0. set beta == alpha
-                        uv2.addBound(InferenceBound.EQ, uv.qtype, infer.types);
+                        uv2.addBound(InferenceBound.EQ, uv, infer.types);
                         //1. copy all alpha's bounds to beta's
                         for (InferenceBound ib : InferenceBound.values()) {
                             for (Type b2 : uv.getBounds(ib)) {
@@ -1090,7 +1094,7 @@
             while (!sstrategy.done()) {
                 InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph);
                 List<Type> varsToSolve = List.from(nodeToSolve.data);
-                inferenceContext.save();
+                List<Type> saved_undet = inferenceContext.save();
                 try {
                     //repeat until all variables are solved
                     outer: while (Type.containsAny(inferenceContext.restvars(), varsToSolve)) {
@@ -1107,7 +1111,7 @@
                 }
                 catch (InferenceException ex) {
                     //did we fail because of interdependent ivars?
-                    inferenceContext.rollback();
+                    inferenceContext.rollback(saved_undet);
                     instantiateAsUninferredVars(varsToSolve, inferenceContext);
                     checkWithinBounds(inferenceContext, warn);
                 }
@@ -1502,7 +1506,7 @@
         /**
          * Save the state of this inference context
          */
-        void save() {
+        List<Type> save() {
             ListBuffer<Type> buf = ListBuffer.lb();
             for (Type t : undetvars) {
                 UndetVar uv = (UndetVar)t;
@@ -1515,16 +1519,24 @@
                 uv2.inst = uv.inst;
                 buf.add(uv2);
             }
-            saved_undet = buf.toList();
+            return buf.toList();
         }
 
         /**
          * Restore the state of this inference context to the previous known checkpoint
          */
-        void rollback() {
-            Assert.check(saved_undet != null && saved_undet.length() == undetvars.length());
-            undetvars = saved_undet;
-            saved_undet = null;
+        void rollback(List<Type> saved_undet) {
+             Assert.check(saved_undet != null && saved_undet.length() == undetvars.length());
+            //restore bounds (note: we need to preserve the old instances)
+            for (Type t : undetvars) {
+                UndetVar uv = (UndetVar)t;
+                UndetVar uv_saved = (UndetVar)saved_undet.head;
+                for (InferenceBound ib : InferenceBound.values()) {
+                    uv.setBounds(ib, uv_saved.getBounds(ib));
+                }
+                uv.inst = uv_saved.inst;
+                saved_undet = saved_undet.tail;
+            }
         }
 
         /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/8019824/T8019824.java	Fri Jul 05 11:05:02 2013 +0100
@@ -0,0 +1,15 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 8019824
+ * @summary very long error messages on inference error
+ * @compile/fail/ref=T8019824.out -XDrawDiagnostics T8019824.java
+ */
+class T8019824 {
+    void test(Class<? extends Foo<?, ?>> cls) {
+        Foo<?, ?> foo = make(cls);
+    }
+
+    <A, B, C extends Foo<A, B>> Foo<A, B> make(Class<C> cls) { return null; }
+
+    interface Foo<A, B> {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/8019824/T8019824.out	Fri Jul 05 11:05:02 2013 +0100
@@ -0,0 +1,2 @@
+T8019824.java:9:25: compiler.err.cant.apply.symbol: kindname.method, make, java.lang.Class<C>, java.lang.Class<compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>>, kindname.class, T8019824, (compiler.misc.incompatible.eq.upper.bounds: C, compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>, T8019824.Foo<java.lang.Object,B>)
+1 error