langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
changeset 31937 ad43a6639c4a
parent 30014 fc1f2b200c1f
child 32709 55d136799f79
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Jul 24 13:08:36 2015 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Jul 24 15:36:45 2015 -0700
@@ -25,7 +25,6 @@
 
 package com.sun.tools.javac.comp;
 
-import com.sun.tools.javac.code.Type.TypeMapping;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCTypeCast;
 import com.sun.tools.javac.tree.TreeInfo;
@@ -112,6 +111,8 @@
                 && options.isUnset("useLegacyInference");
         dependenciesFolder = options.get("dumpInferenceGraphsTo");
         pendingGraphs = List.nil();
+
+        emptyContext = new InferenceContext(this, List.<Type>nil());
     }
 
     /** A value for prototypes that admit any type, including polymorphic ones. */
@@ -170,7 +171,7 @@
                             Resolve.MethodResolutionContext resolveContext,
                             Warner warn) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
-        final InferenceContext inferenceContext = new InferenceContext(tvars);  //B0
+        final InferenceContext inferenceContext = new InferenceContext(this, tvars);  //B0
         inferenceException.clear();
         try {
             DeferredAttr.DeferredAttrContext deferredAttrContext =
@@ -410,7 +411,7 @@
     /**
       * Infer cyclic inference variables as described in 15.12.2.8.
       */
-    private void instantiateAsUninferredVars(List<Type> vars, InferenceContext inferenceContext) {
+    void instantiateAsUninferredVars(List<Type> vars, InferenceContext inferenceContext) {
         ListBuffer<Type> todo = new ListBuffer<>();
         //step 1 - create fresh tvars
         for (Type t : vars) {
@@ -528,7 +529,7 @@
         } else {
             Type formalInterface = funcInterface.tsym.type;
             InferenceContext funcInterfaceContext =
-                    new InferenceContext(funcInterface.tsym.type.getTypeArguments());
+                    new InferenceContext(this, funcInterface.tsym.type.getTypeArguments());
 
             Assert.check(paramTypes != null);
             //get constraints from explicit params (this is done by
@@ -710,7 +711,7 @@
          */
         CHECK_BOUNDS() {
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), infer.types);
                 infer.checkCompatibleUpperBounds(uv, inferenceContext);
                 if (uv.inst != null) {
@@ -746,7 +747,7 @@
          */
         EQ_CHECK_LEGACY() {
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 Type eq = null;
                 for (Type e : uv.getBounds(InferenceBound.EQ)) {
                     Assert.check(!inferenceContext.free(e));
@@ -780,7 +781,7 @@
         EQ_CHECK() {
             @Override
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 for (Type e : uv.getBounds(InferenceBound.EQ)) {
                     if (e.containsAny(inferenceContext.inferenceVars())) continue;
                     for (Type u : uv.getBounds(InferenceBound.UPPER)) {
@@ -807,7 +808,7 @@
          */
         CROSS_UPPER_LOWER() {
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 for (Type b1 : uv.getBounds(InferenceBound.UPPER)) {
                     for (Type b2 : uv.getBounds(InferenceBound.LOWER)) {
                         if (!isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn , infer)) {
@@ -830,7 +831,7 @@
          */
         CROSS_UPPER_EQ() {
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 for (Type b1 : uv.getBounds(InferenceBound.UPPER)) {
                     for (Type b2 : uv.getBounds(InferenceBound.EQ)) {
                         if (!isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn, infer)) {
@@ -853,7 +854,7 @@
          */
         CROSS_EQ_LOWER() {
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 for (Type b1 : uv.getBounds(InferenceBound.EQ)) {
                     for (Type b2 : uv.getBounds(InferenceBound.LOWER)) {
                         if (!isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn, infer)) {
@@ -878,7 +879,7 @@
         CROSS_UPPER_UPPER() {
             @Override
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 List<Type> boundList = uv.getBounds(InferenceBound.UPPER).stream()
                         .collect(infer.types.closureCollector(true, infer.types::isSameType));
                 List<Type> boundListTail = boundList.tail;
@@ -928,7 +929,7 @@
          */
         CROSS_EQ_EQ() {
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 for (Type b1 : uv.getBounds(InferenceBound.EQ)) {
                     for (Type b2 : uv.getBounds(InferenceBound.EQ)) {
                         if (b1 != b2) {
@@ -952,7 +953,7 @@
          */
         PROP_UPPER() {
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 for (Type b : uv.getBounds(InferenceBound.UPPER)) {
                     if (inferenceContext.inferenceVars().contains(b)) {
                         UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b);
@@ -984,7 +985,7 @@
          */
         PROP_LOWER() {
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 for (Type b : uv.getBounds(InferenceBound.LOWER)) {
                     if (inferenceContext.inferenceVars().contains(b)) {
                         UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b);
@@ -1016,7 +1017,7 @@
          */
         PROP_EQ() {
             public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 for (Type b : uv.getBounds(InferenceBound.EQ)) {
                     if (inferenceContext.inferenceVars().contains(b)) {
                         UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b);
@@ -1524,7 +1525,7 @@
         LOWER(InferenceBound.LOWER) {
             @Override
             Type solve(UndetVar uv, InferenceContext inferenceContext) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 List<Type> lobounds = filterBounds(uv, inferenceContext);
                 //note: lobounds should have at least one element
                 Type owntype = lobounds.tail.tail == null  ? lobounds.head : infer.types.lub(lobounds);
@@ -1553,7 +1554,7 @@
                     //not an unbounded undet var
                     return false;
                 }
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 for (Type db : t.getDeclaredBounds()) {
                     if (t.isInterface()) continue;
                     if (infer.types.asSuper(infer.syms.runtimeExceptionType, db.tsym) != null) {
@@ -1567,7 +1568,7 @@
 
             @Override
             Type solve(UndetVar uv, InferenceContext inferenceContext) {
-                return inferenceContext.infer().syms.runtimeExceptionType;
+                return inferenceContext.infer.syms.runtimeExceptionType;
             }
         },
         /**
@@ -1577,7 +1578,7 @@
         UPPER(InferenceBound.UPPER) {
             @Override
             Type solve(UndetVar uv, InferenceContext inferenceContext) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 List<Type> hibounds = filterBounds(uv, inferenceContext);
                 //note: hibounds should have at least one element
                 Type owntype = hibounds.tail.tail == null  ? hibounds.head : infer.types.glb(hibounds);
@@ -1618,7 +1619,7 @@
 
             @Override
             Type solve(UndetVar uv, InferenceContext inferenceContext) {
-                Infer infer = inferenceContext.infer();
+                Infer infer = inferenceContext.infer;
                 Type upper = UPPER.filterBounds(uv, inferenceContext).nonEmpty() ?
                         UPPER.solve(uv, inferenceContext) :
                         infer.syms.objectType;
@@ -2082,419 +2083,6 @@
         void typesInferred(InferenceContext inferenceContext);
     }
 
-    /**
-     * An inference context keeps track of the set of variables that are free
-     * in the current context. It provides utility methods for opening/closing
-     * types to their corresponding free/closed forms. It also provide hooks for
-     * attaching deferred post-inference action (see PendingCheck). Finally,
-     * it can be used as an entry point for performing upper/lower bound inference
-     * (see InferenceKind).
-     */
-     class InferenceContext {
-
-        /** list of inference vars as undet vars */
-        List<Type> undetvars;
-
-        /** list of inference vars in this context */
-        List<Type> inferencevars;
-
-        Map<FreeTypeListener, List<Type>> freeTypeListeners = new HashMap<>();
-
-        List<FreeTypeListener> freetypeListeners = List.nil();
-
-        public InferenceContext(List<Type> inferencevars) {
-            this.undetvars = inferencevars.map(fromTypeVarFun);
-            this.inferencevars = inferencevars;
-        }
-        //where
-            TypeMapping<Void> fromTypeVarFun = new TypeMapping<Void>() {
-                @Override
-                public Type visitTypeVar(TypeVar tv, Void aVoid) {
-                    return new UndetVar(tv, types);
-                }
-
-                @Override
-                public Type visitCapturedType(CapturedType t, Void aVoid) {
-                    return new CapturedUndetVar(t, types);
-                }
-            };
-
-        /**
-         * add a new inference var to this inference context
-         */
-        void addVar(TypeVar t) {
-            this.undetvars = this.undetvars.prepend(fromTypeVarFun.apply(t));
-            this.inferencevars = this.inferencevars.prepend(t);
-        }
-
-        /**
-         * returns the list of free variables (as type-variables) in this
-         * inference context
-         */
-        List<Type> inferenceVars() {
-            return inferencevars;
-        }
-
-        /**
-         * returns the list of uninstantiated variables (as type-variables) in this
-         * inference context
-         */
-        List<Type> restvars() {
-            return filterVars(new Filter<UndetVar>() {
-                public boolean accepts(UndetVar uv) {
-                    return uv.inst == null;
-                }
-            });
-        }
-
-        /**
-         * returns the list of instantiated variables (as type-variables) in this
-         * inference context
-         */
-        List<Type> instvars() {
-            return filterVars(new Filter<UndetVar>() {
-                public boolean accepts(UndetVar uv) {
-                    return uv.inst != null;
-                }
-            });
-        }
-
-        /**
-         * Get list of bounded inference variables (where bound is other than
-         * declared bounds).
-         */
-        final List<Type> boundedVars() {
-            return filterVars(new Filter<UndetVar>() {
-                public boolean accepts(UndetVar uv) {
-                    return uv.getBounds(InferenceBound.UPPER)
-                             .diff(uv.getDeclaredBounds())
-                             .appendList(uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)).nonEmpty();
-                }
-            });
-        }
-
-        /* Returns the corresponding inference variables.
-         */
-        private List<Type> filterVars(Filter<UndetVar> fu) {
-            ListBuffer<Type> res = new ListBuffer<>();
-            for (Type t : undetvars) {
-                UndetVar uv = (UndetVar)t;
-                if (fu.accepts(uv)) {
-                    res.append(uv.qtype);
-                }
-            }
-            return res.toList();
-        }
-
-        /**
-         * is this type free?
-         */
-        final boolean free(Type t) {
-            return t.containsAny(inferencevars);
-        }
-
-        final boolean free(List<Type> ts) {
-            for (Type t : ts) {
-                if (free(t)) return true;
-            }
-            return false;
-        }
-
-        /**
-         * Returns a list of free variables in a given type
-         */
-        final List<Type> freeVarsIn(Type t) {
-            ListBuffer<Type> buf = new ListBuffer<>();
-            for (Type iv : inferenceVars()) {
-                if (t.contains(iv)) {
-                    buf.add(iv);
-                }
-            }
-            return buf.toList();
-        }
-
-        final List<Type> freeVarsIn(List<Type> ts) {
-            ListBuffer<Type> buf = new ListBuffer<>();
-            for (Type t : ts) {
-                buf.appendList(freeVarsIn(t));
-            }
-            ListBuffer<Type> buf2 = new ListBuffer<>();
-            for (Type t : buf) {
-                if (!buf2.contains(t)) {
-                    buf2.add(t);
-                }
-            }
-            return buf2.toList();
-        }
-
-        /**
-         * Replace all free variables in a given type with corresponding
-         * undet vars (used ahead of subtyping/compatibility checks to allow propagation
-         * of inference constraints).
-         */
-        final Type asUndetVar(Type t) {
-            return types.subst(t, inferencevars, undetvars);
-        }
-
-        final List<Type> asUndetVars(List<Type> ts) {
-            ListBuffer<Type> buf = new ListBuffer<>();
-            for (Type t : ts) {
-                buf.append(asUndetVar(t));
-            }
-            return buf.toList();
-        }
-
-        List<Type> instTypes() {
-            ListBuffer<Type> buf = new ListBuffer<>();
-            for (Type t : undetvars) {
-                UndetVar uv = (UndetVar)t;
-                buf.append(uv.inst != null ? uv.inst : uv.qtype);
-            }
-            return buf.toList();
-        }
-
-        /**
-         * Replace all free variables in a given type with corresponding
-         * instantiated types - if one or more free variable has not been
-         * fully instantiated, it will still be available in the resulting type.
-         */
-        Type asInstType(Type t) {
-            return types.subst(t, inferencevars, instTypes());
-        }
-
-        List<Type> asInstTypes(List<Type> ts) {
-            ListBuffer<Type> buf = new ListBuffer<>();
-            for (Type t : ts) {
-                buf.append(asInstType(t));
-            }
-            return buf.toList();
-        }
-
-        /**
-         * Add custom hook for performing post-inference action
-         */
-        void addFreeTypeListener(List<Type> types, FreeTypeListener ftl) {
-            freeTypeListeners.put(ftl, freeVarsIn(types));
-        }
-
-        /**
-         * Mark the inference context as complete and trigger evaluation
-         * of all deferred checks.
-         */
-        void notifyChange() {
-            notifyChange(inferencevars.diff(restvars()));
-        }
-
-        void notifyChange(List<Type> inferredVars) {
-            InferenceException thrownEx = null;
-            for (Map.Entry<FreeTypeListener, List<Type>> entry :
-                    new HashMap<>(freeTypeListeners).entrySet()) {
-                if (!Type.containsAny(entry.getValue(), inferencevars.diff(inferredVars))) {
-                    try {
-                        entry.getKey().typesInferred(this);
-                        freeTypeListeners.remove(entry.getKey());
-                    } catch (InferenceException ex) {
-                        if (thrownEx == null) {
-                            thrownEx = ex;
-                        }
-                    }
-                }
-            }
-            //inference exception multiplexing - present any inference exception
-            //thrown when processing listeners as a single one
-            if (thrownEx != null) {
-                throw thrownEx;
-            }
-        }
-
-        /**
-         * Save the state of this inference context
-         */
-        List<Type> save() {
-            ListBuffer<Type> buf = new ListBuffer<>();
-            for (Type t : undetvars) {
-                UndetVar uv = (UndetVar)t;
-                UndetVar uv2 = new UndetVar((TypeVar)uv.qtype, types);
-                for (InferenceBound ib : InferenceBound.values()) {
-                    for (Type b : uv.getBounds(ib)) {
-                        uv2.addBound(ib, b, types);
-                    }
-                }
-                uv2.inst = uv.inst;
-                buf.add(uv2);
-            }
-            return buf.toList();
-        }
-
-        /**
-         * Restore the state of this inference context to the previous known checkpoint
-         */
-        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;
-            }
-        }
-
-        /**
-         * Copy variable in this inference context to the given context
-         */
-        void dupTo(final InferenceContext that) {
-            that.inferencevars = that.inferencevars.appendList(
-                    inferencevars.diff(that.inferencevars));
-            that.undetvars = that.undetvars.appendList(
-                    undetvars.diff(that.undetvars));
-            //set up listeners to notify original inference contexts as
-            //propagated vars are inferred in new context
-            for (Type t : inferencevars) {
-                that.freeTypeListeners.put(new FreeTypeListener() {
-                    public void typesInferred(InferenceContext inferenceContext) {
-                        InferenceContext.this.notifyChange();
-                    }
-                }, List.of(t));
-            }
-        }
-
-        private void solve(GraphStrategy ss, Warner warn) {
-            solve(ss, new HashMap<Type, Set<Type>>(), warn);
-        }
-
-        /**
-         * Solve with given graph strategy.
-         */
-        private void solve(GraphStrategy ss, Map<Type, Set<Type>> stuckDeps, Warner warn) {
-            GraphSolver s = new GraphSolver(this, stuckDeps, warn);
-            s.solve(ss);
-        }
-
-        /**
-         * Solve all variables in this context.
-         */
-        public void solve(Warner warn) {
-            solve(new LeafSolver() {
-                public boolean done() {
-                    return restvars().isEmpty();
-                }
-            }, warn);
-        }
-
-        /**
-         * Solve all variables in the given list.
-         */
-        public void solve(final List<Type> vars, Warner warn) {
-            solve(new BestLeafSolver(vars) {
-                public boolean done() {
-                    return !free(asInstTypes(vars));
-                }
-            }, warn);
-        }
-
-        /**
-         * Solve at least one variable in given list.
-         */
-        public void solveAny(List<Type> varsToSolve, Map<Type, Set<Type>> optDeps, Warner warn) {
-            solve(new BestLeafSolver(varsToSolve.intersect(restvars())) {
-                public boolean done() {
-                    return instvars().intersect(varsToSolve).nonEmpty();
-                }
-            }, optDeps, warn);
-        }
-
-        /**
-         * Apply a set of inference steps
-         */
-        private boolean solveBasic(EnumSet<InferenceStep> steps) {
-            return solveBasic(inferencevars, steps);
-        }
-
-        private boolean solveBasic(List<Type> varsToSolve, EnumSet<InferenceStep> steps) {
-            boolean changed = false;
-            for (Type t : varsToSolve.intersect(restvars())) {
-                UndetVar uv = (UndetVar)asUndetVar(t);
-                for (InferenceStep step : steps) {
-                    if (step.accepts(uv, this)) {
-                        uv.inst = step.solve(uv, this);
-                        changed = true;
-                        break;
-                    }
-                }
-            }
-            return changed;
-        }
-
-        /**
-         * Instantiate inference variables in legacy mode (JLS 15.12.2.7, 15.12.2.8).
-         * During overload resolution, instantiation is done by doing a partial
-         * inference process using eq/lower bound instantiation. During check,
-         * we also instantiate any remaining vars by repeatedly using eq/upper
-         * instantiation, until all variables are solved.
-         */
-        public void solveLegacy(boolean partial, Warner warn, EnumSet<InferenceStep> steps) {
-            while (true) {
-                boolean stuck = !solveBasic(steps);
-                if (restvars().isEmpty() || partial) {
-                    //all variables have been instantiated - exit
-                    break;
-                } else if (stuck) {
-                    //some variables could not be instantiated because of cycles in
-                    //upper bounds - provide a (possibly recursive) default instantiation
-                    instantiateAsUninferredVars(restvars(), this);
-                    break;
-                } else {
-                    //some variables have been instantiated - replace newly instantiated
-                    //variables in remaining upper bounds and continue
-                    for (Type t : undetvars) {
-                        UndetVar uv = (UndetVar)t;
-                        uv.substBounds(inferenceVars(), instTypes(), types);
-                    }
-                }
-            }
-            checkWithinBounds(this, warn);
-        }
-
-        private Infer infer() {
-            //back-door to infer
-            return Infer.this;
-        }
-
-        @Override
-        public String toString() {
-            return "Inference vars: " + inferencevars + '\n' +
-                   "Undet vars: " + undetvars;
-        }
-
-        /* Method Types.capture() generates a new type every time it's applied
-         * to a wildcard parameterized type. This is intended functionality but
-         * there are some cases when what you need is not to generate a new
-         * captured type but to check that a previously generated captured type
-         * is correct. There are cases when caching a captured type for later
-         * reuse is sound. In general two captures from the same AST are equal.
-         * This is why the tree is used as the key of the map below. This map
-         * stores a Type per AST.
-         */
-        Map<JCTree, Type> captureTypeCache = new HashMap<>();
-
-        Type cachedCapture(JCTree tree, Type t, boolean readOnly) {
-            Type captured = captureTypeCache.get(tree);
-            if (captured != null) {
-                return captured;
-            }
-
-            Type result = types.capture(t);
-            if (result != t && !readOnly) { // then t is a wildcard parameterized type
-                captureTypeCache.put(tree, result);
-            }
-            return result;
-        }
-    }
-
-    final InferenceContext emptyContext = new InferenceContext(List.<Type>nil());
+    final InferenceContext emptyContext;
     // </editor-fold>
 }