changeset 2244:d34073d069c8

8016177: structural most specific and stuckness 8016178: Order of unsticking functional expressions
author mcimadamore
date Thu, 25 Jul 2013 16:29:24 +0100
parents 718064a04b56
children 00274133b7d2
files src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java src/share/classes/com/sun/tools/javac/comp/Infer.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/com/sun/tools/javac/resources/compiler.properties src/share/classes/com/sun/tools/javac/util/GraphUtils.java src/share/classes/com/sun/tools/javac/util/List.java test/tools/javac/diags/examples/CyclicInference.java test/tools/javac/lambda/8016177/T8016177a.java test/tools/javac/lambda/8016177/T8016177a.out test/tools/javac/lambda/8016177/T8016177b.java test/tools/javac/lambda/8016177/T8016177b.out test/tools/javac/lambda/8016177/T8016177c.java test/tools/javac/lambda/8016177/T8016177d.java test/tools/javac/lambda/8016177/T8016177e.java test/tools/javac/lambda/8016177/T8016177f.java test/tools/javac/lambda/MethodReference70.out test/tools/javac/lambda/MethodReference71.out test/tools/javac/lambda/TargetType10.java test/tools/javac/lambda/TargetType10.out test/tools/javac/lambda/TargetType21.java test/tools/javac/lambda/TargetType21.out test/tools/javac/lambda/TargetType26.out test/tools/javac/lambda/TargetType27.out test/tools/javac/lambda/TargetType39.out test/tools/javac/lambda/TargetType57.out test/tools/javac/lambda/typeInference/InferenceTest6.java test/tools/javac/lambda/typeInference/InferenceTest_neg5.java test/tools/javac/lambda/typeInference/InferenceTest_neg5.out test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java
diffstat 29 files changed, 881 insertions(+), 259 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 24 16:54:37 2013 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Thu Jul 25 16:29:24 2013 +0100
@@ -34,18 +34,19 @@
 import com.sun.tools.javac.comp.Attr.ResultInfo;
 import com.sun.tools.javac.comp.Infer.InferenceContext;
 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
+import com.sun.tools.javac.comp.Resolve.ReferenceLookupHelper;
 import com.sun.tools.javac.tree.JCTree.*;
 
-
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.EnumSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
 
 import static com.sun.tools.javac.code.TypeTag.*;
-import com.sun.tools.javac.comp.Resolve.ReferenceLookupHelper;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /**
@@ -98,7 +99,7 @@
         emptyDeferredAttrContext =
             new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
                 @Override
-                void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
+                void addDeferredAttrNode(DeferredType dt, ResultInfo ri, Set<Type> stuckVars, Set<Type> outVars) {
                     Assert.error("Empty deferred context!");
                 }
                 @Override
@@ -144,15 +145,15 @@
 
             class Entry {
                 JCTree speculativeTree;
-                Resolve.MethodResolutionPhase phase;
+                ResultInfo resultInfo;
 
-                public Entry(JCTree speculativeTree, MethodResolutionPhase phase) {
+                public Entry(JCTree speculativeTree, ResultInfo resultInfo) {
                     this.speculativeTree = speculativeTree;
-                    this.phase = phase;
+                    this.resultInfo = resultInfo;
                 }
 
-                boolean matches(Resolve.MethodResolutionPhase phase) {
-                    return this.phase == phase;
+                boolean matches(MethodResolutionPhase phase) {
+                    return resultInfo.checkContext.deferredAttrContext().phase == phase;
                 }
             }
 
@@ -173,12 +174,13 @@
              * Stores a speculative cache entry corresponding to given symbol
              * and resolution phase
              */
-            void put(Symbol msym, JCTree speculativeTree, MethodResolutionPhase phase) {
+            void put(JCTree speculativeTree, ResultInfo resultInfo) {
+                Symbol msym = resultInfo.checkContext.deferredAttrContext().msym;
                 List<Entry> entries = cache.get(msym);
                 if (entries == null) {
                     entries = List.nil();
                 }
-                cache.put(msym, entries.prepend(new Entry(speculativeTree, phase)));
+                cache.put(msym, entries.prepend(new Entry(speculativeTree, resultInfo)));
             }
         }
 
@@ -198,15 +200,17 @@
          * attribution round must follow one or more speculative rounds.
          */
         Type check(ResultInfo resultInfo) {
-            return check(resultInfo, stuckVars(tree, env, resultInfo), basicCompleter);
+            Pair<Set<Type>, Set<Type>> stuckRes = stuckVars(tree, env, resultInfo);
+            return check(resultInfo, stuckRes.fst, stuckRes.snd, basicCompleter);
         }
 
-        Type check(ResultInfo resultInfo, List<Type> stuckVars, DeferredTypeCompleter deferredTypeCompleter) {
+        private Type check(ResultInfo resultInfo, Set<Type> stuckVars, Set<Type> depVars,
+                DeferredTypeCompleter deferredTypeCompleter) {
             DeferredAttrContext deferredAttrContext =
                     resultInfo.checkContext.deferredAttrContext();
             Assert.check(deferredAttrContext != emptyDeferredAttrContext);
-            if (stuckVars.nonEmpty()) {
-                deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars);
+            if (!stuckVars.isEmpty()) {
+                deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars, depVars);
                 return Type.noType;
             } else {
                 try {
@@ -244,7 +248,7 @@
                     //speculative rounds...
                     Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE);
                     JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
-                    dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
+                    dt.speculativeCache.put(speculativeTree, resultInfo);
                     return speculativeTree.type;
                 case CHECK:
                     Assert.check(dt.mode != null);
@@ -383,8 +387,9 @@
          * Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable
          * Nodes added this way act as 'roots' for the out-of-order method checking process.
          */
-        void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
-            deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, stuckVars));
+        void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo,
+                Set<Type> stuckVars, Set<Type> depVars) {
+            deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, stuckVars, depVars));
         }
 
         /**
@@ -395,13 +400,26 @@
          */
         void complete() {
             while (!deferredAttrNodes.isEmpty()) {
-                Set<Type> stuckVars = new LinkedHashSet<Type>();
+                Map<Type, Set<Type>> depVarsMap = new LinkedHashMap<Type, Set<Type>>();
+                List<Type> stuckVars = List.nil();
                 boolean progress = false;
                 //scan a defensive copy of the node list - this is because a deferred
                 //attribution round can add new nodes to the list
                 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
                     if (!deferredAttrNode.process(this)) {
-                        stuckVars.addAll(deferredAttrNode.stuckVars);
+                        List<Type> restStuckVars = List.from(deferredAttrNode.stuckVars)
+                                .intersect(inferenceContext.restvars());
+                        stuckVars = stuckVars.prependList(restStuckVars);
+                        //update dependency map
+                        for (Type t : List.from(deferredAttrNode.depVars)
+                                .intersect(inferenceContext.restvars())) {
+                            Set<Type> prevDeps = depVarsMap.get(t);
+                            if (prevDeps == null) {
+                                prevDeps = new LinkedHashSet<Type>();
+                                depVarsMap.put(t, prevDeps);
+                            }
+                            prevDeps.addAll(restStuckVars);
+                        }
                     } else {
                         deferredAttrNodes.remove(deferredAttrNode);
                         progress = true;
@@ -410,11 +428,39 @@
                 if (!progress) {
                     //remove all variables that have already been instantiated
                     //from the list of stuck variables
-                    inferenceContext.solveAny(List.from(stuckVars), warn);
-                    inferenceContext.notifyChange();
+                    try {
+                        inferenceContext.solveAny(stuckVars, depVarsMap,
+                                mode == AttrMode.SPECULATIVE ? targetFreevars() : List.<Type>nil(),
+                                warn);
+                        inferenceContext.notifyChange();
+                    } catch (Infer.GraphStrategy.NodeNotFoundException ex) {
+                        //this means that we are in speculative mode and the
+                        //set of contraints are too tight for progess to be made.
+                        //Just leave the remaining expressions as stuck.
+                        break;
+                    }
                 }
             }
         }
+        
+        /**
+         * Get the list of stuck variables that do not depend on the target
+         * type - this means that inference will lead to same results during
+         * both OVERLOAD and CHECK modes.
+         */
+        List<Type> targetFreevars() {
+            List<Type> freevars = msym.type.getTypeArguments();
+            ListBuffer<Type> targetVars = ListBuffer.lb();
+            outer: for (Type t : inferenceContext.inferencevars) {
+                for (Type t2 : freevars) {
+                    if (msym.type.getReturnType().contains(t2) &&
+                            t.tsym == t2.tsym) {
+                        targetVars.append(t);
+                    }
+                }
+            }
+            return targetVars.toList();
+        }
     }
 
     /**
@@ -429,21 +475,26 @@
         /** underlying target type information */
         ResultInfo resultInfo;
 
-        /** list of uninferred inference variables causing this node to be stuck */
-        List<Type> stuckVars;
+        /** set of uninferred inference variables causing this node to be stuck */
+        Set<Type> stuckVars;
+        
+        /** set of uninferred inference variables that depends on this node */
+        Set<Type> depVars;
+        
 
-        DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
+        DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, Set<Type> stuckVars, Set<Type> depVars) {
             this.dt = dt;
             this.resultInfo = resultInfo;
             this.stuckVars = stuckVars;
+            this.depVars = depVars;
             if (!stuckVars.isEmpty()) {
-                resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
+                resultInfo.checkContext.inferenceContext().addFreeTypeListener(List.from(stuckVars), this);
             }
         }
 
         @Override
         public void typesInferred(InferenceContext inferenceContext) {
-            stuckVars = List.nil();
+            stuckVars.clear();
             resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
         }
 
@@ -452,24 +503,42 @@
          * Invariant: a stuck node cannot be processed.
          */
         @SuppressWarnings("fallthrough")
-        boolean process(DeferredAttrContext deferredAttrContext) {
+        boolean process(final DeferredAttrContext deferredAttrContext) {
             switch (deferredAttrContext.mode) {
                 case SPECULATIVE:
-                    dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
-                    return true;
+                    if (!stuckVars.isEmpty()) {
+                        dt.check(resultInfo, Collections.<Type>emptySet(),
+                                    Collections.<Type>emptySet(), new StructuralStuckChecker());
+                        return false;
+                    } else {
+                        dt.check(resultInfo, stuckVars, depVars, basicCompleter);
+                        return true;
+                    }
                 case CHECK:
-                    if (stuckVars.nonEmpty()) {
+                    if (!stuckVars.isEmpty()) {
                         //stuck expression - see if we can propagate
                         if (deferredAttrContext.parent != emptyDeferredAttrContext &&
-                                Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, List.from(stuckVars))) {
-                            deferredAttrContext.parent.deferredAttrNodes.add(this);
-                            dt.check(resultInfo, List.<Type>nil(), dummyCompleter);
+                                Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars,
+                                        List.from(stuckVars))) {
+                            deferredAttrContext.parent.addDeferredAttrNode(dt,
+                                    resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
+                                @Override
+                                public InferenceContext inferenceContext() {
+                                    return deferredAttrContext.parent.inferenceContext;
+                                }
+                                @Override
+                                public DeferredAttrContext deferredAttrContext() {
+                                    return deferredAttrContext.parent;
+                                }
+                            }), stuckVars, depVars);
+                            dt.check(resultInfo, Collections.<Type>emptySet(),
+                                    Collections.<Type>emptySet(), dummyCompleter);
                             return true;
                         } else {
                             return false;
                         }
                     } else {
-                        dt.check(resultInfo, stuckVars, basicCompleter);
+                        dt.check(resultInfo, stuckVars, depVars, basicCompleter);
                         return true;
                     }
                 default:
@@ -489,7 +558,7 @@
                 this.resultInfo = resultInfo;
                 this.inferenceContext = deferredAttrContext.inferenceContext;                
                 dt.tree.accept(this);
-                dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase);
+                dt.speculativeCache.put(stuckTree, resultInfo);
                 return Type.noType;
             }
 
@@ -643,21 +712,22 @@
 
     /**
      * Retrieves the list of inference variables that need to be inferred before
-     * an AST node can be type-checked
+     * an AST node can be type-checked, along with the inference variables that
+     * will get constraints should the stuck expression be type-checked.
      */
     @SuppressWarnings("fallthrough")
-    List<Type> stuckVars(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
-                if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
-            return List.nil();
+    Pair<Set<Type>, Set<Type>> stuckVars(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
+        if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
+            return new Pair<Set<Type>, Set<Type>>(Collections.<Type>emptySet(), Collections.<Type>emptySet());
         } else {
             return stuckVarsInternal(tree, resultInfo.pt, env, resultInfo.checkContext.inferenceContext());
         }
     }
     //where
-        private List<Type> stuckVarsInternal(JCTree tree, Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
+        private Pair<Set<Type>, Set<Type>> stuckVarsInternal(JCTree tree, Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
             StuckChecker sc = new StuckChecker(pt, env, inferenceContext);
             sc.scan(tree);
-            return List.from(sc.stuckVars);
+            return new Pair<Set<Type>, Set<Type>>(sc.stuckVars, sc.depVars);
         }
 
     /**
@@ -738,6 +808,7 @@
         Env<AttrContext> env;
         Infer.InferenceContext inferenceContext;
         Set<Type> stuckVars = new LinkedHashSet<Type>();
+        Set<Type> depVars = new LinkedHashSet<Type>();
 
         StuckChecker(Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
             this.pt = pt;
@@ -758,6 +829,7 @@
             if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
                     freeArgVars.nonEmpty()) {
                 stuckVars.addAll(freeArgVars);
+                depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
             }
             scanLambdaBody(tree, descType.getReturnType());
         }
@@ -797,19 +869,26 @@
                         (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) &&
                         exprTree.type.isRaw())) {
                     stuckVars.addAll(freeArgVars);
+                    depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
                 }
             }
         }
 
         void scanLambdaBody(JCLambda lambda, final Type pt) {
             if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
-                stuckVars.addAll(stuckVarsInternal(lambda.body, pt, env, inferenceContext));
+                Pair<Set<Type>, Set<Type>> stuckRes =
+                        stuckVarsInternal(lambda.body, pt, env, inferenceContext);
+                stuckVars.addAll(stuckRes.fst);
+                depVars.addAll(stuckRes.snd);
             } else {
                 LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
                     @Override
                     public void visitReturn(JCReturn tree) {
                         if (tree.expr != null) {
-                            stuckVars.addAll(stuckVarsInternal(tree.expr, pt, env, inferenceContext));
+                            Pair<Set<Type>, Set<Type>> stuckRes =
+                                    stuckVarsInternal(tree.expr, pt, env, inferenceContext);
+                            stuckVars.addAll(stuckRes.fst);
+                            depVars.addAll(stuckRes.snd);
                         }
                     }
                 };
--- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jul 24 16:54:37 2013 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Jul 25 16:29:24 2013 +0100
@@ -40,17 +40,17 @@
 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node;
 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
-
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
+import com.sun.tools.javac.util.GraphUtils.TarjanNode;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.EnumMap;
 import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
 
 import static com.sun.tools.javac.code.TypeTag.*;
 
@@ -114,6 +114,12 @@
         }
 
         @Override
+        InapplicableMethodException setMessage() {
+            //no message to set
+            return this;
+        }
+
+        @Override
         InapplicableMethodException setMessage(JCDiagnostic diag) {
             messages = messages.append(diag);
             return this;
@@ -171,7 +177,7 @@
                     return mt;
                 }
             }
-
+            
             deferredAttrContext.complete();
 
             // minimize as yet undetermined type variables
@@ -1006,10 +1012,24 @@
      * and (ii) tell th engine when we are done fixing inference variables
      */
     interface GraphStrategy {
+        
+        /**
+         * A NodeNotFoundException is thrown whenever an inference strategy fails
+         * to pick the next node to solve in the inference graph.
+         */
+        public static class NodeNotFoundException extends RuntimeException {
+            private static final long serialVersionUID = 0;
+            
+            InferenceGraph graph;
+
+            public NodeNotFoundException(InferenceGraph graph) {
+                this.graph = graph;
+            }
+        }
         /**
          * Pick the next node (leaf) to solve in the graph
          */
-        Node pickNode(InferenceGraph g);
+        Node pickNode(InferenceGraph g) throws NodeNotFoundException;
         /**
          * Is this the last step?
          */
@@ -1022,7 +1042,10 @@
      */
     abstract class LeafSolver implements GraphStrategy {
         public Node pickNode(InferenceGraph g) {
-                        Assert.check(!g.nodes.isEmpty(), "No nodes to solve!");
+            if (g.nodes.isEmpty()) {
+                //should not happen
+                throw new NodeNotFoundException(g);
+            };
             return g.nodes.get(0);
         }
     }
@@ -1034,61 +1057,84 @@
      */
     abstract class BestLeafSolver extends LeafSolver {
 
+        /** list of ivars of which at least one must be solved */
         List<Type> varsToSolve;
+        
+        /** list of ivars that the solver should not touch */
+        List<Type> varsToAvoid;
 
-        BestLeafSolver(List<Type> varsToSolve) {
+        BestLeafSolver(List<Type> varsToSolve, List<Type> varsToAvoid) {
             this.varsToSolve = varsToSolve;
+            this.varsToAvoid = varsToAvoid;
         }
 
         /**
-         * Computes the minimum path that goes from a given node to any of the nodes
-         * containing a variable in {@code varsToSolve}. For any given path, the cost
-         * is computed as the total number of type-variables that should be eagerly
-         * instantiated across that path.
+         * Computes a path that goes from a given node to the leafs in the graph.
+         * Typically this will start from a node containing a variable in
+         * {@code varsToSolve}. For any given path, the cost is computed as the total
+         * number of type-variables that should be eagerly instantiated across that path.
          */
-        int computeMinPath(InferenceGraph g, Node n) {
-            return computeMinPath(g, n, List.<Node>nil(), 0);
+        Pair<List<Node>, Integer> computeTreeToLeafs(Node n) {
+            Pair<List<Node>, Integer> cachedPath = treeCache.get(n);
+            if (cachedPath == null) {
+                //cache miss
+                if (n.isLeaf()) {
+                    //if leaf, stop
+                    cachedPath = new Pair<List<Node>, Integer>(List.of(n), n.data.length());
+                } else {
+                   //if non-leaf, proceed recursively
+                   Pair<List<Node>, Integer> path = new Pair<List<Node>, Integer>(List.of(n), n.data.length());
+                   for (Node n2 : n.getAllDependencies()) {
+                       if (n2 == n) continue;
+                       Pair<List<Node>, Integer> subpath = computeTreeToLeafs(n2);
+                       path = new Pair<List<Node>, Integer>(
+                               path.fst.prependList(subpath.fst),
+                               path.snd + subpath.snd);
+                   }
+                   cachedPath = path;
+                }
+                //save results in cache
+                treeCache.put(n, cachedPath);
+            }
+            return cachedPath;
         }
         
-        int computeMinPath(InferenceGraph g, Node n, List<Node> path, int cost) {
-            if (path.contains(n)) return Integer.MAX_VALUE;
-            List<Node> path2 = path.prepend(n);
-            int cost2 = cost + n.data.size();
-            if (!Collections.disjoint(n.data, varsToSolve)) {
-                return cost2;
-            } else {
-               int bestPath = Integer.MAX_VALUE;
-               for (Node n2 : g.nodes) {
-                   if (n2.deps.contains(n)) {
-                       int res = computeMinPath(g, n2, path2, cost2);
-                       if (res < bestPath) {
-                           bestPath = res;
-                       }
-                   }
-                }
-               return bestPath;
-            }
-        }
+        /** cache used to avoid redundant computation of tree costs */
+        final Map<Node, Pair<List<Node>, Integer>> treeCache =
+                new HashMap<Node, Pair<List<Node>, Integer>>();
+        
+        /** constant value used to mark non-existent paths */
+        final Pair<List<Node>, Integer> noPath =
+                    new Pair<List<Node>, Integer>(null, Integer.MAX_VALUE);
 
         /**
          * Pick the leaf that minimize cost
          */
         @Override
         public Node pickNode(final InferenceGraph g) {
-            final Map<Node, Integer> leavesMap = new HashMap<Node, Integer>();
+            treeCache.clear(); //graph changes at every step - cache must be cleared
+            Pair<List<Node>, Integer> bestPath = noPath;
+            Set<Node> avoidClosure = new LinkedHashSet<Node>();
+            //compute closure of all variables to avoid
+            for (Type t : varsToAvoid) {
+                avoidClosure.addAll(g.findNode(t).closure(DependencyKind.BOUND));
+            }
             for (Node n : g.nodes) {
-                if (n.isLeaf(n)) {
-                    leavesMap.put(n, computeMinPath(g, n));
+                if (!Collections.disjoint(n.data, varsToSolve)) {
+                    Pair<List<Node>, Integer> path = computeTreeToLeafs(n);
+                    //discard all paths containing at least a node in the
+                    //closure computed above
+                    if (Collections.disjoint(path.fst, avoidClosure) &&
+                            path.snd < bestPath.snd) {
+                        bestPath = path;
+                    }
                 }
             }
-            Assert.check(!leavesMap.isEmpty(), "No nodes to solve!");
-            TreeSet<Node> orderedLeaves = new TreeSet<Node>(new Comparator<Node>() {
-                public int compare(Node n1, Node n2) {
-                    return leavesMap.get(n1) - leavesMap.get(n2);
-                }
-            });
-            orderedLeaves.addAll(leavesMap.keySet());
-            return orderedLeaves.first();
+            if (bestPath == noPath) {
+                //no path leads there
+                throw new NodeNotFoundException(g);
+            }
+            return bestPath.fst.head;
         }
     }
 
@@ -1286,6 +1332,33 @@
             this.steps = steps;
         }
     }
+    
+    /**
+     * There are two kinds of dependencies between inference variables. The basic
+     * kind of dependency (or bound dependency) arises when a variable mention
+     * another variable in one of its bounds. There's also a more subtle kind
+     * of dependency that arises when a variable 'might' lead to better constraints
+     * on another variable (this is typically the case with variables holding up
+     * stuck expressions).
+     */
+    enum DependencyKind implements GraphUtils.DependencyKind {
+        
+        /** bound dependency */
+        BOUND("dotted"),
+        /** stuck dependency */
+        STUCK("dashed");
+        
+        final String dotSyle;
+
+        private DependencyKind(String dotSyle) {
+            this.dotSyle = dotSyle;
+        }
+
+        @Override
+        public String toDotStyle() {
+            return dotSyle;
+        }
+    }
 
     /**
      * This is the graph inference solver - the solver organizes all inference variables in
@@ -1298,10 +1371,12 @@
     class GraphSolver {
 
         InferenceContext inferenceContext;
+        Map<Type, Set<Type>> stuckDeps;
         Warner warn;
 
-        GraphSolver(InferenceContext inferenceContext, Warner warn) {
+        GraphSolver(InferenceContext inferenceContext, Map<Type, Set<Type>> stuckDeps, Warner warn) {
             this.inferenceContext = inferenceContext;
+            this.stuckDeps = stuckDeps;
             this.warn = warn;
         }
 
@@ -1312,7 +1387,7 @@
          */
         void solve(GraphStrategy sstrategy) {
             checkWithinBounds(inferenceContext, warn); //initial propagation of bounds
-            InferenceGraph inferenceGraph = new InferenceGraph();
+            InferenceGraph inferenceGraph = new InferenceGraph(stuckDeps);
             while (!sstrategy.done()) {
                 InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph);
                 List<Type> varsToSolve = List.from(nodeToSolve.data);
@@ -1357,64 +1432,172 @@
              */
             class Node extends GraphUtils.TarjanNode<ListBuffer<Type>> {
 
-                Set<Node> deps;
+                /** map listing all dependencies (grouped by kind) */
+                EnumMap<DependencyKind, Set<Node>> deps;
 
                 Node(Type ivar) {
                     super(ListBuffer.of(ivar));
-                    this.deps = new HashSet<Node>();
+                    this.deps = new EnumMap<DependencyKind, Set<Node>>(DependencyKind.class);
                 }
 
                 @Override
-                public Iterable<? extends Node> getDependencies() {
-                    return deps;
+                public GraphUtils.DependencyKind[] getSupportedDependencyKinds() {
+                    return DependencyKind.values();
+                }
+                
+                @Override
+                public String getDependencyName(GraphUtils.Node<ListBuffer<Type>> to, GraphUtils.DependencyKind dk) {
+                    if (dk == DependencyKind.STUCK) return "";
+                    else {
+                        StringBuilder buf = new StringBuilder();
+                        String sep = "";
+                        for (Type from : data) {
+                            UndetVar uv = (UndetVar)inferenceContext.asFree(from);
+                            for (Type bound : uv.getBounds(InferenceBound.values())) {
+                                if (bound.containsAny(List.from(to.data))) {
+                                    buf.append(sep);
+                                    buf.append(bound);
+                                    sep = ",";
+                                }
+                            }
+                        }
+                        return buf.toString();
+                    }
+                }
+                
+                @Override
+                public Iterable<? extends Node> getAllDependencies() {
+                    return getDependencies(DependencyKind.values());
                 }
 
                 @Override
-                public String printDependency(GraphUtils.Node<ListBuffer<Type>> to) {
-                    StringBuilder buf = new StringBuilder();
-                    String sep = "";
-                    for (Type from : data) {
-                        UndetVar uv = (UndetVar)inferenceContext.asFree(from);
-                        for (Type bound : uv.getBounds(InferenceBound.values())) {
-                            if (bound.containsAny(List.from(to.data))) {
-                                buf.append(sep);
-                                buf.append(bound);
-                                sep = ",";
-                            }
+                public Iterable<? extends TarjanNode<ListBuffer<Type>>> getDependenciesByKind(GraphUtils.DependencyKind dk) {
+                    return getDependencies((DependencyKind)dk);
+                }
+                
+                /**
+                 * Retrieves all dependencies with given kind(s).
+                 */
+                protected Set<Node> getDependencies(DependencyKind... depKinds) {
+                    Set<Node> buf = new LinkedHashSet<Node>();
+                    for (DependencyKind dk : depKinds) {
+                        Set<Node> depsByKind = deps.get(dk);
+                        if (depsByKind != null) {
+                            buf.addAll(depsByKind);
                         }
                     }
-                    return buf.toString();
+                    return buf;
+                }
+                
+                /**
+                 * Adds dependency with given kind.
+                 */
+                protected void addDependency(DependencyKind dk, Node depToAdd) {
+                    Set<Node> depsByKind = deps.get(dk);
+                    if (depsByKind == null) {
+                        depsByKind = new LinkedHashSet<Node>();
+                        deps.put(dk, depsByKind);
+                    }
+                    depsByKind.add(depToAdd);
+                }
+                
+                /**
+                 * Add multiple dependencies of same given kind.
+                 */
+                protected void addDependencies(DependencyKind dk, Set<Node> depsToAdd) {
+                    for (Node n : depsToAdd) {
+                        addDependency(dk, n);
+                    }
+                }
+                
+                /**
+                 * Remove a dependency, regardless of its kind.
+                 */
+                protected Set<DependencyKind> removeDependency(Node n) {
+                    Set<DependencyKind> removedKinds = new HashSet<>();
+                    for (DependencyKind dk : DependencyKind.values()) {
+                        Set<Node> depsByKind = deps.get(dk);
+                        if (depsByKind == null) continue;
+                        if (depsByKind.remove(n)) {
+                            removedKinds.add(dk);
+                        }
+                    }
+                    return removedKinds;
+                }
+                
+                /**
+                 * Compute closure of a give node, by recursively walking
+                 * through all its dependencies (of given kinds)
+                 */
+                protected Set<Node> closure(DependencyKind... depKinds) {
+                    boolean progress = true;
+                    Set<Node> closure = new HashSet<Node>();
+                    closure.add(this);
+                    while (progress) {
+                        progress = false;
+                        for (Node n1 : new HashSet<Node>(closure)) {
+                            progress = closure.addAll(n1.getDependencies(depKinds));
+                        }
+                    }
+                    return closure;
                 }
 
-                boolean isLeaf(Node n) {
+                /**
+                 * Is this node a leaf? This means either the node has no dependencies,
+                 * or it just has self-dependencies.
+                 */
+                protected boolean isLeaf() {
                     //no deps, or only one self dep
-                    return (n.deps.isEmpty() ||
-                            n.deps.size() == 1 && n.deps.contains(n));
+                    Set<Node> allDeps = getDependencies(DependencyKind.BOUND, DependencyKind.STUCK);
+                    if (allDeps.isEmpty()) return true;
+                    for (Node n : allDeps) {
+                        if (n != this) {
+                            return false;
+                        }
+                    }
+                    return true;
                 }
 
-                void mergeWith(List<? extends Node> nodes) {
+                /**
+                 * Merge this node with another node, acquiring its dependencies.
+                 * This routine is used to merge all cyclic node together and
+                 * form an acyclic graph.
+                 */
+                protected void mergeWith(List<? extends Node> nodes) {
                     for (Node n : nodes) {
                         Assert.check(n.data.length() == 1, "Attempt to merge a compound node!");
                         data.appendList(n.data);
-                        deps.addAll(n.deps);
+                        for (DependencyKind dk : DependencyKind.values()) {
+                            addDependencies(dk, n.getDependencies(dk));
+                        }
                     }
                     //update deps
-                    Set<Node> deps2 = new HashSet<Node>();
-                    for (Node d : deps) {
-                        if (data.contains(d.data.first())) {
-                            deps2.add(this);
-                        } else {
-                            deps2.add(d);
+                    EnumMap<DependencyKind, Set<Node>> deps2 = new EnumMap<DependencyKind, Set<Node>>(DependencyKind.class);
+                    for (DependencyKind dk : DependencyKind.values()) {
+                        for (Node d : getDependencies(dk)) {
+                            Set<Node> depsByKind = deps2.get(dk);
+                            if (depsByKind == null) {
+                                depsByKind = new LinkedHashSet<Node>();
+                                deps2.put(dk, depsByKind);
+                            }
+                            if (data.contains(d.data.first())) {
+                                depsByKind.add(this);
+                            } else {
+                                depsByKind.add(d);
+                            }
                         }
                     }
                     deps = deps2;
                 }
 
-                void graphChanged(Node from, Node to) {
-                    if (deps.contains(from)) {
-                        deps.remove(from);
+                /**
+                 * Notify all nodes that something has changed in the graph
+                 * topology.
+                 */
+                private void graphChanged(Node from, Node to) {
+                    for (DependencyKind dk : removeDependency(from)) {
                         if (to != null) {
-                            deps.add(to);
+                            addDependency(dk, to);
                         }
                     }
                 }
@@ -1423,8 +1606,21 @@
             /** the nodes in the inference graph */
             ArrayList<Node> nodes;
 
-            InferenceGraph() {
-                initNodes();
+            InferenceGraph(Map<Type, Set<Type>> optDeps) {
+                initNodes(optDeps);
+            }
+            
+            /**
+             * Basic lookup helper for retrieving a graph node given an inference
+             * variable type.
+             */
+            public Node findNode(Type t) {
+                for (Node n : nodes) {
+                    if (n.data.contains(t)) {
+                        return n;
+                    }
+                }
+                return null;
             }
 
             /**
@@ -1451,24 +1647,32 @@
              * Create the graph nodes. First a simple node is created for every inference
              * variables to be solved. Then Tarjan is used to found all connected components
              * in the graph. For each component containing more than one node, a super node is
-                 * created, effectively replacing the original cyclic nodes.
+             * created, effectively replacing the original cyclic nodes.
              */
-            void initNodes() {
+            void initNodes(Map<Type, Set<Type>> stuckDeps) {
+                //add nodes
                 nodes = new ArrayList<Node>();
                 for (Type t : inferenceContext.restvars()) {
                     nodes.add(new Node(t));
                 }
+                //add dependencies
                 for (Node n_i : nodes) {
                     Type i = n_i.data.first();
+                    Set<Type> optDepsByNode = stuckDeps.get(i);
                     for (Node n_j : nodes) {
                         Type j = n_j.data.first();
                         UndetVar uv_i = (UndetVar)inferenceContext.asFree(i);
                         if (Type.containsAny(uv_i.getBounds(InferenceBound.values()), List.of(j))) {
-                            //update i's deps
-                            n_i.deps.add(n_j);
+                            //update i's bound dependencies
+                            n_i.addDependency(DependencyKind.BOUND, n_j);
+                        }
+                        if (optDepsByNode != null && optDepsByNode.contains(j)) {
+                            //update i's stuck dependencies
+                            n_i.addDependency(DependencyKind.STUCK, n_j);
                         }
                     }
                 }
+                //merge cyclic nodes
                 ArrayList<Node> acyclicNodes = new ArrayList<Node>();
                 for (List<? extends Node> conSubGraph : GraphUtils.tarjan(nodes)) {
                     if (conSubGraph.length() > 1) {
@@ -1596,12 +1800,12 @@
             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();
+                             .diff(uv.getDeclaredBounds())
+                             .appendList(uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)).nonEmpty();
                 }
             });
         }
-
+        
         private List<Type> filterVars(Filter<UndetVar> fu) {
             ListBuffer<Type> res = ListBuffer.lb();
             for (Type t : undetvars) {
@@ -1786,12 +1990,16 @@
                 }, 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, Warner warn) {
-            GraphSolver s = new GraphSolver(this, warn);
+        private void solve(GraphStrategy ss, Map<Type, Set<Type>> stuckDeps, Warner warn) {
+            GraphSolver s = new GraphSolver(this, stuckDeps, warn);
             s.solve(ss);
         }
 
@@ -1810,7 +2018,7 @@
          * Solve all variables in the given list.
          */
         public void solve(final List<Type> vars, Warner warn) {
-            solve(new BestLeafSolver(vars) {
+            solve(new BestLeafSolver(vars, List.<Type>nil()) {
                 public boolean done() {
                     return !free(asInstTypes(vars));
                 }
@@ -1820,18 +2028,12 @@
         /**
          * Solve at least one variable in given list.
          */
-        public void solveAny(List<Type> varsToSolve, Warner warn) {
-            checkWithinBounds(this, warn); //propagate bounds
-            List<Type> boundedVars = boundedVars().intersect(restvars()).intersect(varsToSolve);
-            if (boundedVars.isEmpty()) {
-                throw inferenceException.setMessage("cyclic.inference",
-                                freeVarsIn(varsToSolve));
-            }
-            solve(new BestLeafSolver(boundedVars) {
+        public void solveAny(List<Type> varsToSolve, Map<Type, Set<Type>> optDeps, List<Type> varsToAvoid, Warner warn) {
+            solve(new BestLeafSolver(varsToSolve.intersect(restvars()), varsToAvoid) {
                 public boolean done() {
                     return instvars().intersect(varsToSolve).nonEmpty();
                 }
-            }, warn);
+            }, optDeps, warn);
         }
 
         /**
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jul 24 16:54:37 2013 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Jul 25 16:29:24 2013 +0100
@@ -643,7 +643,7 @@
          * Retrieve the method check object that will be used during a
          * most specific check.
          */
-        MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict);
+        MethodCheck mostSpecificCheck(Symbol other, List<Type> actuals, boolean strict);
     }
 
     /**
@@ -689,7 +689,7 @@
             //do nothing - method always applicable regardless of actuals
         }
 
-        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+        public MethodCheck mostSpecificCheck(Symbol other, List<Type> actuals, boolean strict) {
             return this;
         }
     };
@@ -764,7 +764,7 @@
             throw ex.setMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args));
         }
 
-        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+        public MethodCheck mostSpecificCheck(Symbol other, List<Type> actuals, boolean strict) {
             return nilMethodCheck;
         }
     }
@@ -860,8 +860,8 @@
         }
 
         @Override
-        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
-            return new MostSpecificCheck(strict, actuals);
+        public MethodCheck mostSpecificCheck(Symbol other, List<Type> actuals, boolean strict) {
+            return new MostSpecificCheck(other, strict, actuals);
         }
     };
 
@@ -907,8 +907,8 @@
         }
 
         @Override
-        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
-            return new MostSpecificCheck(strict, actuals);
+        public MethodCheck mostSpecificCheck(Symbol other, List<Type> actuals, boolean strict) {
+            return new MostSpecificCheck(other, strict, actuals);
         }
     };
 
@@ -1005,8 +1005,10 @@
 
         boolean strict;
         List<Type> actuals;
-
-        MostSpecificCheck(boolean strict, List<Type> actuals) {
+        Symbol other;
+
+        MostSpecificCheck(Symbol other, boolean strict, List<Type> actuals) {
+            this.other = other;
             this.strict = strict;
             this.actuals = actuals;
         }
@@ -1057,14 +1059,32 @@
                     switch (actual.getTag()) {
                         case DEFERRED:
                             DeferredType dt = (DeferredType) actual;
-                            DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
-                            return (e == null || e.speculativeTree == deferredAttr.stuckTree)
-                                    ? false : mostSpecific(found, req, e.speculativeTree, warn);
+                            DeferredType.SpeculativeCache.Entry e1 = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
+                            DeferredType.SpeculativeCache.Entry e2 = dt.speculativeCache.get(other, deferredAttrContext.phase);
+                            return (e1 == null || e2 == null ||
+                                    e1.speculativeTree == deferredAttr.stuckTree ||
+                                    e2.speculativeTree == deferredAttr.stuckTree) ?
+                                            super.compatible(found, req, warn) :
+                                            mostSpecific(e2.resultInfo.pt, patchPt(e1), e1.speculativeTree, warn);
                         default:
                             return standaloneMostSpecific(found, req, actual, warn);
                     }
                 }
             }
+            
+            /**
+             * We need to fixup inference variables in the speculative cache and
+             * replace them the inference variables bring used by the most specific check.
+             */
+            Type patchPt(DeferredType.SpeculativeCache.Entry e) {
+                List<Type> inferenceVarsFrom =
+                        e.resultInfo.checkContext.inferenceContext().inferencevars;
+                List<Type> inferenceVarsTo =
+                        deferredAttrContext.inferenceContext.inferencevars;
+                return types.subst(e.resultInfo.pt,
+                        inferenceVarsFrom.at(inferenceVarsTo.length()), //original method vars are in front
+                        inferenceVarsTo);
+            }
 
             private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) {
                 MostSpecificChecker msc = new MostSpecificChecker(t, s, warn);
@@ -1201,7 +1221,7 @@
             }
         }
 
-        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+        public MethodCheck mostSpecificCheck(Symbol other, List<Type> actuals, boolean strict) {
             Assert.error("Cannot get here!");
             return null;
         }
@@ -1526,7 +1546,7 @@
             currentResolutionContext = new MethodResolutionContext();
             currentResolutionContext.step = prevResolutionContext.step;
             currentResolutionContext.methodCheck =
-                    prevResolutionContext.methodCheck.mostSpecificCheck(actuals, !allowBoxing);
+                    prevResolutionContext.methodCheck.mostSpecificCheck(m1, actuals, !allowBoxing);
             Type mst = instantiate(env, site, m2, null,
                     adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null,
                     allowBoxing, useVarargs, noteWarner);
@@ -3905,6 +3925,16 @@
                     return (JCDiagnostic)((JCDiagnostic)d.getArgs()[0]).getArgs()[1];
                 }
             });
+            
+            rewriters.put(new Template(argMismatchRegex, skip, new Template("(.*)(bad.arg.types.in.lambda)", skip, skip)),
+                    new DiagnosticRewriter() {
+                @Override
+                public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
+                        DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
+                        DiagnosticType preferredKind, JCDiagnostic d) {
+                    return (JCDiagnostic)((JCDiagnostic)d.getArgs()[1]).getArgs()[1];
+                }
+            });
 
             rewriters.put(new Template(argMismatchRegex, skip),
                     new DiagnosticRewriter() {
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Jul 24 16:54:37 2013 -0700
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Jul 25 16:29:24 2013 +0100
@@ -1901,10 +1901,6 @@
     inferred: {0}\n\
     equality constraints(s): {1}
 
-# 0: list of type
-compiler.misc.cyclic.inference=\
-    Cannot instantiate inference variables {0} because of an inference loop
-
 # 0: symbol
 compiler.misc.diamond=\
     {0}<>
--- a/src/share/classes/com/sun/tools/javac/util/GraphUtils.java	Wed Jul 24 16:54:37 2013 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/GraphUtils.java	Thu Jul 25 16:29:24 2013 +0100
@@ -31,6 +31,18 @@
  *  deletion without notice.</b>
  */
 public class GraphUtils {
+    
+    /**
+     * Basic interface for defining various dependency kinds. All dependency kinds
+     * must at least support basic capabilities to tell the DOT engine how to render them.
+     */
+    public interface DependencyKind {
+        /**
+         * Returns the DOT representation (to be used in a {@code style} attribute
+         * that's most suited for this dependency kind.
+         */
+        String toDotStyle();
+    }
 
     /**
      * This class is a basic abstract class for representing a node.
@@ -42,10 +54,21 @@
         public Node(D data) {
             this.data = data;
         }
+        
+        /**
+         * Get an array of the dependency kinds supported by this node.
+         */
+        public abstract DependencyKind[] getSupportedDependencyKinds();
 
-        public abstract Iterable<? extends Node<D>> getDependencies();
+        /**
+         * Get all dependencies, regardless of their kind.
+         */
+        public abstract Iterable<? extends Node<D>> getAllDependencies();
 
-        public abstract String printDependency(Node<D> to);
+        /**
+         * Get a name for the dependency (of given kind) linking this node to a given node
+         */
+        public abstract String getDependencyName(Node<D> to, DependencyKind dk);
 
         @Override
         public String toString() {
@@ -66,7 +89,9 @@
             super(data);
         }
 
-        public abstract Iterable<? extends TarjanNode<D>> getDependencies();
+        public abstract Iterable<? extends TarjanNode<D>> getAllDependencies();
+        
+        public abstract Iterable<? extends TarjanNode<D>> getDependenciesByKind(DependencyKind dk);
 
         public int compareTo(TarjanNode<D> o) {
             return (index < o.index) ? -1 : (index == o.index) ? 0 : 1;
@@ -95,7 +120,7 @@
         index++;
         stack.prepend(v);
         v.active = true;
-        for (TarjanNode<D> nd: v.getDependencies()) {
+        for (TarjanNode<D> nd: v.getAllDependencies()) {
             @SuppressWarnings("unchecked")
             N n = (N)nd;
             if (n.index == -1) {
@@ -134,9 +159,11 @@
         }
         //dump arcs
         for (TarjanNode<D> from : nodes) {
-            for (TarjanNode<D> to : from.getDependencies()) {
-                buf.append(String.format("%s -> %s [label = \" %s \"];\n",
-                        from.hashCode(), to.hashCode(), from.printDependency(to)));
+            for (DependencyKind dk : from.getSupportedDependencyKinds()) {
+                for (TarjanNode<D> to : from.getDependenciesByKind(dk)) {
+                    buf.append(String.format("%s -> %s [label = \" %s \" style = %s ];\n",
+                            from.hashCode(), to.hashCode(), from.getDependencyName(to, dk), dk.toDotStyle()));
+                }
             }
         }
         buf.append("}\n");
--- a/src/share/classes/com/sun/tools/javac/util/List.java	Wed Jul 24 16:54:37 2013 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/List.java	Thu Jul 25 16:29:24 2013 +0100
@@ -115,6 +115,16 @@
         }
         return buf.toList();
     }
+    
+    public List<A> at(int pos) {
+        ListBuffer<A> buf = ListBuffer.lb();
+        int count = 0;
+        for (A el : this) {
+            if (count++ == pos) break;
+            buf.append(el);
+        }
+        return buf.toList();
+    }
 
     /** Construct a list consisting of given element.
      */
--- a/test/tools/javac/diags/examples/CyclicInference.java	Wed Jul 24 16:54:37 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.prob.found.req
-// key: compiler.misc.cyclic.inference
-
-class CyclicInference {
-    interface SAM<X> {
-        void m(X x);
-    }
-
-    <Z> void g(SAM<Z> sz) { }
-
-    void test() {
-        g(x-> {});
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/8016177/T8016177a.java	Thu Jul 25 16:29:24 2013 +0100
@@ -0,0 +1,45 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8016177 8016178
+ * @summary structural most specific and stuckness
+ * @compile/fail/ref=T8016177a.out -XDrawDiagnostics T8016177a.java
+ */
+import java.util.List;
+
+class T8016177a {
+
+    interface ToIntFunction<X> {
+        int m(X x);
+    }
+
+    interface Function<X, Y> {
+        Y m(X x);
+    }
+
+    <T,R> void m1(List<T> s, Function<T,R> f) { }
+    <T,R> void m1(List<T> s, ToIntFunction<T> f) { }
+
+    <T,R> List<R> m2(List<T> s, Function<T,R> f) { return null; }
+    <T,R> List<R> m2(List<T> s, ToIntFunction<T> f) { return null; }
+
+    <T,R> List<T> m3(List<T> s, Function<T,R> f) { return null; }
+    <T,R> List<R> m3(List<T> s, ToIntFunction<T> f) { return null; }
+
+    <T,R> List<T> m4(List<T> s, Function<T,R> f) { return null; }
+    <T,R> List<T> m4(List<T> s, ToIntFunction<T> f) { return null; }
+
+    <T,R> List<R> m5(List<T> s, Function<T,R> f) { return null; }
+    <T,R> List<T> m5(List<T> s, ToIntFunction<T> f) { return null; }
+    
+    <T extends R,R> List<R> m6(List<T> s, Function<T,R> f) { return null; }
+    <T extends R,R> List<T> m6(List<T> s, ToIntFunction<T> f) { return null; }
+
+    void test(List<String> ss) {
+         m1(ss, s->s.length()); //ok
+         m2(ss, s->s.length()); //ok
+         m3(ss, s->s.length()); //ambiguous
+         m4(ss, s->s.length()); //ambiguous
+         m5(ss, s->s.length()); //ambiguous
+         m6(ss, s->s.length()); //ambiguous
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/8016177/T8016177a.out	Thu Jul 25 16:29:24 2013 +0100
@@ -0,0 +1,6 @@
+T8016177a.java:40:10: compiler.err.ref.ambiguous: m3, kindname.method, <T,R>m3(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m3(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
+T8016177a.java:41:10: compiler.err.ref.ambiguous: m4, kindname.method, <T,R>m4(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m4(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
+T8016177a.java:42:10: compiler.err.ref.ambiguous: m5, kindname.method, <T,R>m5(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m5(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
+T8016177a.java:43:10: compiler.err.ref.ambiguous: m6, kindname.method, <T,R>m6(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m6(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
+T8016177a.java:43:12: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,R, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, java.lang.String)))
+5 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/8016177/T8016177b.java	Thu Jul 25 16:29:24 2013 +0100
@@ -0,0 +1,34 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8016177 8016178
+ * @summary structural most specific and stuckness
+ * @compile/fail/ref=T8016177b.out -XDrawDiagnostics T8016177b.java
+ */
+class T8016177b {
+    interface ToIntFunction<X> {
+        int m(X x);
+    }
+
+    interface Function<X, Y> {
+        Y m(X x);
+    }
+    
+    <U, V> Function<U, V> id(Function<U, V> arg) { return null; }
+
+    <U, V> Function<U, V> id2(Function<U, V> arg) { return null; }
+    <U> ToIntFunction<U> id2(ToIntFunction<U> arg) { return null; }   
+    
+    
+    <X,Y,Z> X f(Y arg, Function<Y, Z> f) { return null; }
+    
+    <X,Y,Z> X f2(Y arg, Function<Y, Z> f) { return null; }
+    <X,Y> X f2(Y arg, ToIntFunction<Y> f) { return null; }
+    
+    <T> T g(T arg) { return null; }
+
+    void test() {
+        g(f("hi", id(x->1))); //ok
+        g(f("hi", id2(x->1))); //ambiguous
+        g(f2("hi", id(x->1))); //ok
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/8016177/T8016177b.out	Thu Jul 25 16:29:24 2013 +0100
@@ -0,0 +1,2 @@
+T8016177b.java:31:19: compiler.err.ref.ambiguous: id2, kindname.method, <U,V>id2(T8016177b.Function<U,V>), T8016177b, kindname.method, <U>id2(T8016177b.ToIntFunction<U>), T8016177b
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/8016177/T8016177c.java	Thu Jul 25 16:29:24 2013 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8016081 8016178
+ * @summary structural most specific and stuckness
+ * @compile T8016177c.java
+ */
+
+class T8016177c {
+
+    interface Function<X, Y> {
+        Y m(X x);
+    }
+
+    interface ExtFunction<X, Y> extends Function<X, Y> { }
+
+    <U, V> U m(Function<U, V> f) { return null; } 
+    <U, V> U m(ExtFunction<U, V> f) { return null; }
+    
+    void test() { m(x->1); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/8016177/T8016177d.java	Thu Jul 25 16:29:24 2013 +0100
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8016081 8016178
+ * @summary structural most specific and stuckness
+ * @compile T8016177d.java
+ */
+import java.util.*;
+
+class T8016177d {
+
+    interface UnaryOperator<X> {
+      X m(X x);
+    }
+
+    interface IntStream {
+       IntStream sorted();
+       IntStream distinct();
+       IntStream limit(int i);
+    }
+
+    abstract class WrappingUnaryOperator<S> implements UnaryOperator<S>  { }
+
+    <S1> WrappingUnaryOperator<S1> wrap1(UnaryOperator<S1> uo) { return null; }
+    <S2> WrappingUnaryOperator<S2> wrap2(UnaryOperator<S2> uo) { return null; }
+    <S3> WrappingUnaryOperator<S3> wrap3(UnaryOperator<S3> uo) { return null; }
+
+    <P> List<List<P>> perm(List<P> l) { return null; }
+
+    List<List<WrappingUnaryOperator<IntStream>>> intPermutationOfFunctions = 
+                perm(Arrays.asList(
+                        wrap1(s -> s.sorted()),
+                        wrap2(s -> s.distinct()),
+                        wrap3(s -> s.limit(5))
+                ));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/8016177/T8016177e.java	Thu Jul 25 16:29:24 2013 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8016081 8016178
+ * @summary structural most specific and stuckness
+ * @compile T8016177e.java
+ */
+import java.util.*;
+
+class T8016177e {
+    
+    interface TerminalOp<X, Y> { }
+
+    interface Consumer<X> {
+        void m(X x);
+    }
+
+    <T> TerminalOp<T, Void> makeRef(Consumer<? super T> action) { return null; }
+
+    <T> void test() {
+        Map<T, Boolean> map = null;
+        TerminalOp<T, Void> forEachOp = makeRef(t -> { map.put(t, null); });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/8016177/T8016177f.java	Thu Jul 25 16:29:24 2013 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8016081 8016178
+ * @summary structural most specific and stuckness
+ * @compile T8016177f.java
+ */
+import java.util.*;
+
+class T8016177f {
+
+    interface Function<S, T> {
+       T apply(S s);
+    }
+
+    interface IntFunction<T> {
+       T apply(int s);
+    }
+
+
+    interface BiConsumer<X,Y> {
+       void m(X x, Y y);
+    }
+
+    interface Consumer<X> {
+       void m(X x);
+    }
+
+    interface Supplier<X> {
+       X make();
+    }
+
+    interface TestData<T, S extends BaseStream<T, S>> {
+       interface OfRef<T> extends TestData<T, Stream<T>> { }
+       interface OfDouble extends TestData<Double, DoubleStream> { }
+    }
+
+    interface BaseStream<T, S extends BaseStream<T, S>> { }
+
+    interface Stream<T> extends BaseStream<T, Stream<T>> { 
+       <M> Stream<M> map(Function<T, M> s);
+       <R> R collect(Supplier<R> resultFactory, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
+       <Z> Z[] toArray(IntFunction<Z[]> s);
+    }
+
+    interface DoubleStream extends BaseStream<Double, DoubleStream> {
+       DoubleStream filter(DoublePredicate dp);
+       double[] toArray();
+    }
+
+    interface DoublePredicate {
+       boolean p(double d);
+    }
+
+    <T, U, R, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>> 
+           R exerciseTerminalOps(TestData<T, S_IN> data,
+                                 Function<S_IN, S_OUT> streamF,
+                                 Function<S_OUT, R> terminalF) { return null; }
+    
+    <O> TestData.OfRef<O> ofCollection(Collection<O> collection) { return null; }
+
+    void test1(TestData.OfDouble data, DoublePredicate dp) {
+        exerciseTerminalOps(data, s -> s.filter(dp), s -> s.toArray());
+    }
+
+    void test2(Function<Double, Integer> fdi, TestData.OfRef<Double> td, Stream<Integer> si) {
+        exerciseTerminalOps(
+                        ofCollection((List<Double>)null),
+                        s -> s.map(fdi),
+                        s -> s.toArray(Integer[]::new));
+    }
+}
--- a/test/tools/javac/lambda/MethodReference70.out	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/MethodReference70.out	Thu Jul 25 16:29:24 2013 +0100
@@ -1,3 +1,2 @@
-MethodReference70.java:26:10: compiler.err.ref.ambiguous: g, kindname.method, <Z>g(MethodReference70.F<Z>), MethodReference70, kindname.method, <Z>g(MethodReference70.G<Z>), MethodReference70
-MethodReference70.java:26:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z)
-2 errors
+MethodReference70.java:26:10: compiler.err.cant.apply.symbols: kindname.method, g, @553,{(compiler.misc.inapplicable.method: kindname.method, MethodReference70, <Z>g(MethodReference70.F<Z>), (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbols: kindname.method, m2, java.lang.Object,{(compiler.misc.inapplicable.method: kindname.method, MethodReference70, m2(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer))),(compiler.misc.inapplicable.method: kindname.method, MethodReference70, m2(java.lang.String), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))})))),(compiler.misc.inapplicable.method: kindname.method, MethodReference70, <Z>g(MethodReference70.G<Z>), (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbols: kindname.method, m2, java.lang.Object,{(compiler.misc.inapplicable.method: kindname.method, MethodReference70, m2(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer))),(compiler.misc.inapplicable.method: kindname.method, MethodReference70, m2(java.lang.String), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))}))))}
+1 error
--- a/test/tools/javac/lambda/MethodReference71.out	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/MethodReference71.out	Thu Jul 25 16:29:24 2013 +0100
@@ -1,3 +1,2 @@
-MethodReference71.java:24:10: compiler.err.ref.ambiguous: g, kindname.method, <Z>g(MethodReference71.F<Z>), MethodReference71, kindname.method, <Z>g(MethodReference71.G<Z>), MethodReference71
-MethodReference71.java:24:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z)
-2 errors
+MethodReference71.java:24:10: compiler.err.cant.apply.symbols: kindname.method, g, @523,{(compiler.misc.inapplicable.method: kindname.method, MethodReference71, <Z>g(MethodReference71.F<Z>), (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m2, java.lang.Integer[], java.lang.Object, kindname.class, MethodReference71, (compiler.misc.varargs.argument.mismatch: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer)))))),(compiler.misc.inapplicable.method: kindname.method, MethodReference71, <Z>g(MethodReference71.G<Z>), (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m2, java.lang.Integer[], java.lang.Object, kindname.class, MethodReference71, (compiler.misc.varargs.argument.mismatch: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer))))))}
+1 error
--- a/test/tools/javac/lambda/TargetType10.java	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/TargetType10.java	Thu Jul 25 16:29:24 2013 +0100
@@ -1,10 +1,10 @@
 /*
  * @test /nodynamiccopyright/
- * @bug 8003280
+ * @bug 8003280 8016177
  * @summary Add lambda tests
  *  check that wildcards in the target method of a lambda conversion is handled correctly
  * @author  Maurizio Cimadamore
- * @compile/fail/ref=TargetType10.out -XDrawDiagnostics TargetType10.java
+ * @compile TargetType10.java
  */
 
 class TargetType10 {
--- a/test/tools/javac/lambda/TargetType10.out	Wed Jul 24 16:54:37 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-TargetType10.java:17:18: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: B,A)
-1 error
--- a/test/tools/javac/lambda/TargetType21.java	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/TargetType21.java	Thu Jul 25 16:29:24 2013 +0100
@@ -26,8 +26,8 @@
 
     void test() {
         call(x -> { throw new Exception(); }); //ambiguous
-        call(x -> { System.out.println(""); }); //ambiguous
-        call(x -> { return (Object) null; }); //cyclic inference
+        call(x -> { System.out.println(""); }); //ok (only one is void)
+        call(x -> { return (Object) null; }); //ok (only one returns Object)
         call(x -> { return null; }); //ambiguous
     }
 }
--- a/test/tools/javac/lambda/TargetType21.out	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/TargetType21.out	Thu Jul 25 16:29:24 2013 +0100
@@ -1,6 +1,4 @@
 TargetType21.java:28:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
 TargetType21.java:28:14: compiler.err.incompatible.thrown.types.in.lambda: java.lang.Exception
-TargetType21.java:29:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
-TargetType21.java:30:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: A)
 TargetType21.java:31:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
-5 errors
+3 errors
--- a/test/tools/javac/lambda/TargetType26.out	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/TargetType26.out	Thu Jul 25 16:29:24 2013 +0100
@@ -1,2 +1,2 @@
-TargetType26.java:16:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z)
+TargetType26.java:16:7: compiler.err.cant.apply.symbol: kindname.method, call, Z, @340, kindname.class, TargetType26, (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.not.a.functional.intf: java.lang.Object))
 1 error
--- a/test/tools/javac/lambda/TargetType27.out	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/TargetType27.out	Thu Jul 25 16:29:24 2013 +0100
@@ -1,2 +1,2 @@
-TargetType27.java:18:10: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: R)
+TargetType27.java:18:10: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: A,R, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.not.a.functional.intf: java.lang.Object)))
 1 error
--- a/test/tools/javac/lambda/TargetType39.out	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/TargetType39.out	Thu Jul 25 16:29:24 2013 +0100
@@ -1,3 +1,3 @@
-TargetType39.java:19:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: U)
-TargetType39.java:20:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: V)
+TargetType39.java:19:9: compiler.err.cant.apply.symbol: kindname.method, call, TargetType39.SAM<U,V>, @442, kindname.class, TargetType39, (compiler.misc.infer.no.conforming.assignment.exists: U,V, (compiler.misc.incompatible.type.in.conditional: (compiler.misc.inconvertible.types: TargetType39.SAM<java.lang.String,java.lang.Void>, TargetType39.SAM<java.lang.Object,V>)))
+TargetType39.java:20:9: compiler.err.cant.apply.symbol: kindname.method, call, TargetType39.SAM<U,V>, @479, kindname.class, TargetType39, (compiler.misc.infer.no.conforming.assignment.exists: U,V, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.type.in.conditional: (compiler.misc.not.a.functional.intf: java.lang.Object))))
 2 errors
--- a/test/tools/javac/lambda/TargetType57.out	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/TargetType57.out	Thu Jul 25 16:29:24 2013 +0100
@@ -1,2 +1,2 @@
-TargetType57.java:14:42: compiler.err.cant.resolve.location.args: kindname.method, nonExistentMethod, , , (compiler.misc.location.1: kindname.variable, s, java.lang.Integer)
+TargetType57.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List<S_IN>,java.util.function.Function<S_IN,S_OUT>,java.util.function.Function<S_OUT,R>, java.util.List<java.lang.Integer>,@340,@359, kindname.class, TargetType57, (compiler.misc.infer.no.conforming.assignment.exists: U,R,S_IN,S_OUT, (compiler.misc.bad.arg.types.in.lambda: java.lang.Integer, (compiler.err.cant.resolve.location.args: kindname.method, nonExistentMethod, , , (compiler.misc.location.1: kindname.variable, s, java.lang.Integer))))
 1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/typeInference/InferenceTest6.java	Thu Jul 25 16:29:24 2013 +0100
@@ -0,0 +1,26 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8003280 8016177
+ * @summary Add lambda tests
+ *  Missing cast to SAM type that causes type inference to not work.
+ * @compile -XDrawDiagnostics InferenceTest6.java
+ */
+
+import java.util.*;
+
+public class InferenceTest6 {
+    public static void main(String[] args) {
+        InferenceTest6 test = new InferenceTest6();
+        test.method1(n -> {});
+        test.method1((SAM1<String>)n -> {});
+        test.method1((SAM1<Integer>)n -> {n++;});
+        test.method1((SAM1<Comparator<String>>)n -> {List<String> list = Arrays.asList("string1", "string2"); Collections.sort(list,n);});
+        test.method1((SAM1<Thread>)n -> {n.start();});
+    }
+
+    interface SAM1<X> {
+        void m1(X arg);
+    }
+
+    <X> void method1(SAM1<X> s) {}
+}
--- a/test/tools/javac/lambda/typeInference/InferenceTest_neg5.java	Wed Jul 24 16:54:37 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 8003280
- * @summary Add lambda tests
- *  Missing cast to SAM type that causes type inference to not work.
- * @compile/fail/ref=InferenceTest_neg5.out -XDrawDiagnostics InferenceTest_neg5.java
- */
-
-import java.util.*;
-
-public class InferenceTest_neg5 {
-    public static void main(String[] args) {
-        InferenceTest_neg5 test = new InferenceTest_neg5();
-        test.method1(n -> {});
-        test.method1((SAM1<String>)n -> {});
-        test.method1((SAM1<Integer>)n -> {n++;});
-        test.method1((SAM1<Comparator<String>>)n -> {List<String> list = Arrays.asList("string1", "string2"); Collections.sort(list,n);});
-        test.method1((SAM1<Thread>)n -> {n.start();});
-    }
-
-    interface SAM1<X> {
-        void m1(X arg);
-    }
-
-    <X> void method1(SAM1<X> s) {}
-}
--- a/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out	Wed Jul 24 16:54:37 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-InferenceTest_neg5.java:14:21: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: X)
-1 error
--- a/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java	Wed Jul 24 16:54:37 2013 -0700
+++ b/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java	Thu Jul 25 16:29:24 2013 +0100
@@ -227,12 +227,7 @@
         }
         else if (lambdaBodyType != LambdaBody.RETURN_ARG)
             return false;
-        if (  genericDeclKind == GenericDeclKind.GENERIC_NOBOUND ||
-                genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
-            if ( parameterType == TypeKind.GENERIC &&
-                    parameterKind == ParameterKind.IMPLICIT) //cyclic inference
-                return false;
-        }
+
         return true;
     }