changeset 1702:1f2fbcd0de7e

Enhancement: Implement overload resolution as per latest spec EDR *) Restructure DeferredAttr to allow pluggable deferred type completers *) Add 'potentially applicable' phase for stuck arguments as a pluggable deferred completer *) Delay instantiation of stuck ivars until after overload resolution *) Restructure method check code to allow pluggable checkers *) Implement new structural most specific routine as pluggable method check *) Flatten AmbiguityError class *) Delay merging of abstract ambiguous signatures until end of overload resolution *) Lambda/method reference type-checking always use loose check context
author mcimadamore
date Mon, 17 Dec 2012 15:36:20 +0000
parents 0a0392566a68
children 4014132b136e
files src/share/classes/com/sun/tools/javac/code/Source.java src/share/classes/com/sun/tools/javac/code/Types.java src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Check.java src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java src/share/classes/com/sun/tools/javac/comp/GraphInfer.java src/share/classes/com/sun/tools/javac/comp/Infer.java src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/share/classes/com/sun/tools/javac/comp/LegacyInfer.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/com/sun/tools/javac/tree/JCTree.java src/share/classes/com/sun/tools/javac/tree/Pretty.java src/share/classes/com/sun/tools/javac/tree/TreeInfo.java test/tools/javac/Diagnostics/6722234/T6722234d_1.out test/tools/javac/Diagnostics/6722234/T6722234d_2.out test/tools/javac/diags/examples.not-yet.txt test/tools/javac/diags/examples/CyclicInference.java test/tools/javac/diags/examples/InferredDoNotConformToLower.java test/tools/javac/diags/examples/NoUniqueMaximalInstance.java test/tools/javac/diags/examples/WhereIntersection.java test/tools/javac/failover/CheckAttributedTree.java test/tools/javac/generics/diamond/T6939780.out test/tools/javac/generics/diamond/neg/Neg05.out test/tools/javac/generics/diamond/neg/Neg10.java test/tools/javac/generics/inference/6315770/T6315770.out test/tools/javac/generics/inference/6638712/T6638712b.out test/tools/javac/generics/inference/6650759/T6650759m.out test/tools/javac/lambda/MethodReference25.java test/tools/javac/lambda/MethodReference25.out test/tools/javac/lambda/MethodReference26.java test/tools/javac/lambda/MethodReference26.out test/tools/javac/lambda/MethodReference43.java test/tools/javac/lambda/TargetType01.java test/tools/javac/lambda/TargetType01.out test/tools/javac/lambda/TargetType06.java test/tools/javac/lambda/TargetType10.out test/tools/javac/lambda/TargetType11.java test/tools/javac/lambda/TargetType14.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/TargetType28.out test/tools/javac/lambda/TargetType39.out test/tools/javac/lambda/TargetType45.java test/tools/javac/lambda/TargetType45.out test/tools/javac/lambda/TargetType50.out test/tools/javac/lambda/TargetType51.java test/tools/javac/lambda/VoidCompatibility.java test/tools/javac/lambda/VoidCompatibility.out test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java test/tools/javac/lambda/methodReference/SamConversion.java test/tools/javac/lambda/methodReference/SamConversionComboTest.java test/tools/javac/lambda/typeInference/InferenceTest_neg5.out test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java
diffstat 55 files changed, 1148 insertions(+), 865 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Source.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/code/Source.java	Mon Dec 17 15:36:20 2012 +0000
@@ -224,6 +224,9 @@
     public boolean allowBetterInference() {
         return compareTo(JDK1_8) >= 0;
     }
+    public boolean allowStructuralMostSpecific() {
+        return compareTo(JDK1_8) >= 0;
+    }
     public static SourceVersion toSourceVersion(Source source) {
         switch(source) {
         case JDK1_2:
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Mon Dec 17 15:36:20 2012 +0000
@@ -354,8 +354,29 @@
                 return descSym;
             }
 
-            public Type getType(Type origin) {
-                return memberType(origin, descSym);
+            public Type getType(Type site) {
+                if (capture(site) != site) {
+                    Type formalInterface = site.tsym.type;
+                    ListBuffer<Type> typeargs = ListBuffer.lb();
+                    List<Type> actualTypeargs = site.getTypeArguments();
+                    //simply replace the wildcards with its bound
+                    for (Type t : formalInterface.getTypeArguments()) {
+                        if (actualTypeargs.head.hasTag(WILDCARD)) {
+                            WildcardType wt = (WildcardType)actualTypeargs.head;
+                            typeargs.append(wt.type);
+                        } else {
+                            typeargs.append(actualTypeargs.head);
+                        }
+                        actualTypeargs = actualTypeargs.tail;
+                    }
+                    site = subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList());
+                    if (!chk.checkValidGenericType(site)) {
+                        //if the inferred functional interface type is not well-formed,
+                        //or if it's not a subtype of the original target, issue an error
+                        throw failure(diags.fragment("no.suitable.functional.intf.inst", site));
+                    }
+                }
+                return memberType(site, descSym);
             }
         }
 
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Dec 17 15:36:20 2012 +0000
@@ -1376,18 +1376,19 @@
     public void visitConditional(JCConditional tree) {
         Type condtype = attribExpr(tree.cond, env, syms.booleanType);
 
-        boolean standaloneConditional = !allowPoly ||
+        tree.polyKind = (!allowPoly ||
                 pt().hasTag(NONE) && pt() != Type.recoveryType ||
-                isBooleanOrNumeric(env, tree);
-
-        if (!standaloneConditional && resultInfo.pt.hasTag(VOID)) {
+                isBooleanOrNumeric(env, tree)) ?
+                PolyKind.STANDALONE : PolyKind.POLY;
+
+        if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
             //cannot get here (i.e. it means we are returning from void method - which is already an error)
             resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void"));
             result = tree.type = types.createErrorType(resultInfo.pt);
             return;
         }
 
-        ResultInfo condInfo = standaloneConditional ?
+        ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
                 unknownExprInfo :
                 resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
                     //this will use enclosing check context to check compatibility of
@@ -1402,7 +1403,7 @@
         Type truetype = attribTree(tree.truepart, env, condInfo);
         Type falsetype = attribTree(tree.falsepart, env, condInfo);
 
-        Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt();
+        Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt();
         if (condtype.constValue() != null &&
                 truetype.constValue() != null &&
                 falsetype.constValue() != null &&
@@ -1424,12 +1425,30 @@
                     JCConditional condTree = (JCConditional)tree;
                     return isBooleanOrNumeric(env, condTree.truepart) &&
                             isBooleanOrNumeric(env, condTree.falsepart);
+                case APPLY:
+                    JCMethodInvocation speculativeMethodTree =
+                            (JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo);
+                    Type owntype = TreeInfo.symbol(speculativeMethodTree.meth).type.getReturnType();
+                    return types.unboxedTypeOrType(owntype).isPrimitive();
+                case NEWCLASS:
+                    JCExpression className =
+                            removeClassParams.translate(((JCNewClass)tree).clazz);
+                    JCExpression speculativeNewClassTree =
+                            (JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo);
+                    return types.unboxedTypeOrType(speculativeNewClassTree.type).isPrimitive();
                 default:
                     Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type;
                     speculativeType = types.unboxedTypeOrType(speculativeType);
                     return speculativeType.isPrimitive();
             }
         }
+        //where
+            TreeTranslator removeClassParams = new TreeTranslator() {
+                @Override
+                public void visitTypeApply(JCTypeApply tree) {
+                    result = translate(tree.clazz);
+                }
+            };
 
         /** Compute the type of a conditional expression, after
          *  checking that it exists.  See JLS 15.25. Does not take into
@@ -2173,17 +2192,18 @@
         boolean needsRecovery =
                 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK;
         try {
+            Type target = pt();
             List<Type> explicitParamTypes = null;
-            if (TreeInfo.isExplicitLambda(that)) {
+            if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) {
                 //attribute lambda parameters
                 attribStats(that.params, localEnv);
                 explicitParamTypes = TreeInfo.types(that.params);
+                target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext);
             }
 
-            Type target;
             Type lambdaType;
             if (pt() != Type.recoveryType) {
-                target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), explicitParamTypes, resultInfo.checkContext);
+                target = checkIntersectionTarget(that, target, resultInfo.checkContext);
                 lambdaType = types.findDescriptorType(target);
                 chk.checkFunctionalInterface(that, target);
             } else {
@@ -2191,7 +2211,7 @@
                 lambdaType = fallbackDescriptorType(that);
             }
 
-            setFunctionalInfo(that, target, resultInfo.checkContext.inferenceContext());
+            setFunctionalInfo(that, pt(), lambdaType, resultInfo.checkContext.inferenceContext());
 
             if (lambdaType.hasTag(FORALL)) {
                 //lambda expression target desc cannot be a generic method
@@ -2201,7 +2221,7 @@
                 return;
             }
 
-            if (!TreeInfo.isExplicitLambda(that)) {
+            if (that.paramKind == JCLambda.ParameterKind.IMPLICIT) {
                 //add param type info in the AST
                 List<Type> actuals = lambdaType.getParameterTypes();
                 List<JCVariableDecl> params = that.params;
@@ -2284,8 +2304,7 @@
         }
     }
 
-    private Type checkIntersectionTarget(DiagnosticPosition pos, ResultInfo resultInfo) {
-        Type pt = resultInfo.pt;
+    private Type checkIntersectionTarget(DiagnosticPosition pos, Type pt, CheckContext checkContext) {
         if (pt != Type.recoveryType && pt.isCompound()) {            
             IntersectionClassType ict = (IntersectionClassType)pt;
             List<Type> bounds = ict.allInterfaces ?
@@ -2294,7 +2313,7 @@
             types.findDescriptorType(bounds.head); //propagate exception outwards!
             for (Type bound : bounds.tail) {
                 if (!types.isMarkerInterface(bound)) {
-                    resultInfo.checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound));
+                    checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound));
                 }
             }
             //for now (translation doesn't support intersection types)
@@ -2343,7 +2362,7 @@
         }
 
         /**
-         * Lambda/method reference have a special check context that ensures
+         * Lambda have a special check context that ensures
          * that i.e. a lambda return type is compatible with the expected
          * type according to both the inherited context and the assignment
          * context.
@@ -2357,9 +2376,9 @@
             @Override
             public boolean compatible(Type found, Type req, Warner warn) {
                 //return type must be compatible in both current context and assignment context
-                return types.isAssignable(found, inferenceContext().asFree(req, types), warn) &&
-                        super.compatible(found, req, warn);
+                return chk.basicHandler.compatible(found, inferenceContext().asFree(req, types), warn);
             }
+
             @Override
             public void report(DiagnosticPosition pos, JCDiagnostic details) {
                 enclosingContext.report(pos, diags.fragment("incompatible.ret.type.in.lambda", details));
@@ -2475,7 +2494,7 @@
             Type target;
             Type desc;
             if (pt() != Type.recoveryType) {
-                target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), null, resultInfo.checkContext);
+                target = checkIntersectionTarget(that, pt(), resultInfo.checkContext);
                 desc = types.findDescriptorType(target);
                 chk.checkFunctionalInterface(that, target);
             } else {
@@ -2483,13 +2502,11 @@
                 desc = fallbackDescriptorType(that);
             }
 
-            setFunctionalInfo(that, target, resultInfo.checkContext.inferenceContext());
+            setFunctionalInfo(that, pt(), desc, resultInfo.checkContext.inferenceContext());
             List<Type> argtypes = desc.getParameterTypes();
 
-            boolean allowBoxing =
-                    resultInfo.checkContext.deferredAttrContext().phase.isBoxingRequired();
             Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that,
-                    that.expr.type, that.name, argtypes, typeargtypes, allowBoxing);
+                    that.expr.type, that.name, argtypes, typeargtypes, true);
 
             Symbol refSym = refResult.fst;
             Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
@@ -2637,45 +2654,32 @@
             }
         }
     }
-    
-    public class FunctionalInfo {
-        
-        List<Symbol> targets = List.nil();
-        boolean isSerializable;
-        Type targetType;
-
-        FunctionalInfo(Type pt, Type targetType) {
-            if (pt.hasTag(CLASS) && pt.isCompound()) {
-                for (Type t : ((IntersectionClassType)pt).interfaces_field) {
-                    targets = targets.append(t.tsym);
-                }
-            } else {
-                targets = targets.prepend(pt.tsym);
-            }
-            isSerializable = types.asSuper(pt, syms.serializableType.tsym) != null;
-            this.targetType = targetType;
-        }
-    }
-    
-    private void setFunctionalInfo(final JCTree tree, final Type targetType, InferenceContext inferenceContext) {
-        if (inferenceContext.free(targetType)) {
-            inferenceContext.addFreeTypeListener(List.of(targetType), new FreeTypeListener() {
+
+    /**
+     * Set functional type info on the underlying AST. Note: as the target descriptor
+     * might contain inference variables, we might need to register an hook in the
+     * current inference context.
+     */
+    private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, final Type descriptorType, InferenceContext inferenceContext) {
+        if (inferenceContext.free(descriptorType)) {
+            inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() {
                 public void typesInferred(InferenceContext inferenceContext) {
-                    setFunctionalInfo(tree, inferenceContext.asInstType(targetType, types), inferenceContext);
+                    setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType, types), inferenceContext);
                 }
             });
         } else {
-            FunctionalInfo fInfo = new FunctionalInfo(pt(), targetType);
-            switch (tree.getTag()) {
-                case LAMBDA:
-                    ((JCLambda)tree).fInfo = fInfo;
-                    break;
-                case REFERENCE:
-                    ((JCMemberReference)tree).fInfo = fInfo;
-                    break;
-                default:
-                    throw new AssertionError("Bad tree kind " + tree.getTag());
+            ListBuffer<Symbol> targets = ListBuffer.lb();
+            if (pt.hasTag(CLASS)) {
+                if (pt.isCompound()) {
+                    for (Type t : ((IntersectionClassType)pt()).interfaces_field) {
+                        targets.append(t.tsym);
+                    }
+                } else {
+                    targets.append(pt.tsym);
+                }
             }
+            fExpr.targets = targets.toList();
+            fExpr.descriptorType = descriptorType;
         }
     }
 
@@ -4133,11 +4137,28 @@
         }
 
         @Override
+        public void visitLambda(JCLambda that) {
+            super.visitLambda(that);
+            if (that.descriptorType == null) {
+                that.descriptorType = syms.unknownType;
+            }
+            if (that.targets == null) {
+                that.targets = List.nil();
+            }
+        }
+
+        @Override
         public void visitReference(JCMemberReference that) {
             super.visitReference(that);
             if (that.sym == null) {
                 that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol);
             }
+            if (that.descriptorType == null) {
+                that.descriptorType = syms.unknownType;
+            }
+            if (that.targets == null) {
+                that.targets = List.nil();
+            }
         }
     }
     // </editor-fold>
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 17 15:36:20 2012 +0000
@@ -888,7 +888,6 @@
                    syms.methodClass);
         }
         if (useVarargs) {
-            JCTree tree = env.tree;
             Type argtype = owntype.getParameterTypes().last();
             if (!types.isReifiable(argtype) &&
                     (!allowSimplifiedVarargs ||
@@ -899,22 +898,13 @@
                                   argtype);
             }
             if (!((MethodSymbol)sym.baseSymbol()).isSignaturePolymorphic(types)) {
-                Type elemtype = types.elemtype(argtype);
-                switch (tree.getTag()) {
-                    case APPLY:
-                        ((JCMethodInvocation) tree).varargsElement = elemtype;
-                        break;
-                    case NEWCLASS:
-                        ((JCNewClass) tree).varargsElement = elemtype;
-                        break;
-                    case REFERENCE:
-                        ((JCMemberReference) tree).varargsElement = elemtype;
-                        break;
-                    default:
-                        throw new AssertionError(""+tree);
-                }
+                TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype));
             }
          }
+         PolyKind pkind = (sym.type.hasTag(FORALL) &&
+                 sym.type.getReturnType().containsAny(((ForAll)sym.type).tvars)) ?
+                 PolyKind.POLY : PolyKind.STANDALONE;
+         TreeInfo.setPolyKind(env.tree, pkind);
          return owntype;
     }
     //where
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Mon Dec 17 15:36:20 2012 +0000
@@ -38,6 +38,7 @@
 import javax.tools.JavaFileObject;
 
 import java.util.ArrayList;
+import java.util.EnumSet;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Queue;
@@ -64,6 +65,7 @@
 
     final Attr attr;
     final Check chk;
+    final JCDiagnostic.Factory diags;
     final Enter enter;
     final Infer infer;
     final Log log;
@@ -82,13 +84,19 @@
         context.put(deferredAttrKey, this);
         attr = Attr.instance(context);
         chk = Check.instance(context);
+        diags = JCDiagnostic.Factory.instance(context);
         enter = Enter.instance(context);
         infer = InferFactory.instance(context).getInfer();
         log = Log.instance(context);
         syms = Symtab.instance(context);
         make = TreeMaker.instance(context);
         types = Types.instance(context);
+        Names names = Names.instance(context);
+        stuckTree = make.Ident(names.empty).setType(Type.noType);
     }
+    
+    /** shared tree for stuck expressions */
+    final JCTree stuckTree;
 
     /**
      * This type represents a deferred type. A deferred type starts off with
@@ -177,35 +185,62 @@
          * attribution round must follow one or more speculative rounds.
          */
         Type check(ResultInfo resultInfo) {
+            return check(resultInfo, stuckVars(tree, env, resultInfo), basicCompleter);
+        }
+
+        Type check(ResultInfo resultInfo, List<Type> stuckVars, DeferredTypeCompleter deferredTypeCompleter) {
             DeferredAttrContext deferredAttrContext =
                     resultInfo.checkContext.deferredAttrContext();
             Assert.check(deferredAttrContext != emptyDeferredAttrContext);
-            List<Type> stuckVars = stuckVars(tree, env, resultInfo);
             if (stuckVars.nonEmpty()) {
                 deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars);
                 return Type.noType;
             } else {
                 try {
-                    switch (deferredAttrContext.mode) {
-                        case SPECULATIVE:
-                            Assert.check(mode == null ||
-                                    (mode == AttrMode.SPECULATIVE &&
-                                    speculativeType(deferredAttrContext.msym, deferredAttrContext.phase).hasTag(NONE)));
-                            JCTree speculativeTree = attribSpeculative(tree, env, resultInfo);
-                            speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
-                            return speculativeTree.type;
-                        case CHECK:
-                            Assert.check(mode == AttrMode.SPECULATIVE);
-                            return attr.attribTree(tree, env, resultInfo);
-                    }
-                    Assert.error();
-                    return null;
+                    return deferredTypeCompleter.complete(this, resultInfo, deferredAttrContext);
                 } finally {
                     mode = deferredAttrContext.mode;
                 }
             }
         }
     }
+    
+    /**
+     * A completer for deferred types. Defines an entry point for type-checking
+     * a deferred type.
+     */
+    interface DeferredTypeCompleter {
+        /**
+         * Entry point for type-checking a deferred type. Depending on the
+         * circumstances, type-checking could amount to full attribution
+         * or partial structural check (aka potential applicability).
+         */
+        Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext);
+    }
+    
+    /**
+     * A basic completer for deferred types. This completer type-checks a deferred type
+     * using attribution; depending on the attribution mode, this could be either standard
+     * or speculative attribution.
+     */
+    DeferredTypeCompleter basicCompleter = new DeferredTypeCompleter() {
+        public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
+            switch (deferredAttrContext.mode) {
+                case SPECULATIVE:
+                    Assert.check(dt.mode == null ||
+                            (dt.mode == AttrMode.SPECULATIVE &&
+                            dt.speculativeType(deferredAttrContext.msym, deferredAttrContext.phase).hasTag(NONE)));
+                    JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
+                    dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
+                    return speculativeTree.type;
+                case CHECK:
+                    Assert.check(dt.mode == AttrMode.SPECULATIVE);
+                    return attr.attribTree(dt.tree, dt.env, resultInfo);
+            }
+            Assert.error();
+            return null;
+        }
+    };
 
     /**
      * The 'mode' in which the deferred type is to be type-checked
@@ -328,12 +363,11 @@
                 //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.isStuck()) {
-                        deferredAttrNode.process();
+                    if (!deferredAttrNode.process()) {
+                        stuckVars.addAll(deferredAttrNode.stuckVars);
+                    } else {
                         deferredAttrNodes.remove(deferredAttrNode);
                         progress = true;
-                    } else {
-                        stuckVars.addAll(deferredAttrNode.stuckVars);
                     }
                 }
                 if (!progress) {
@@ -376,21 +410,72 @@
             }
 
             /**
-             * is this node stuck?
-             */
-            boolean isStuck() {
-                return stuckVars.nonEmpty();
-            }
-
-            /**
              * Process a deferred attribution node.
              * Invariant: a stuck node cannot be processed.
              */
-            void process() {
-                if (isStuck()) {
-                    throw new IllegalStateException("Cannot process a stuck deferred node");
+            @SuppressWarnings("fallthrough")
+            boolean process() {
+                switch (mode) {
+                    case SPECULATIVE:
+                        dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
+                        return true;
+                    case CHECK:
+                        if (stuckVars.nonEmpty()) {
+                            return false;
+                        } else {
+                            dt.check(resultInfo, stuckVars, basicCompleter);
+                            return true;
+                        }
+                    default:
+                        throw new AssertionError("Bad mode");
                 }
-                dt.check(resultInfo);
+            }
+            
+            /**
+             * Structural checker for stuck expressions
+             */
+            class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
+                
+                ResultInfo resultInfo;
+
+                public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
+                    this.resultInfo = resultInfo;
+                    dt.tree.accept(this);
+                    dt.speculativeCache.put(msym, stuckTree, phase);
+                    return Type.noType;
+                }
+
+                @Override
+                public void visitLambda(JCLambda tree) {
+                    Check.CheckContext checkContext = resultInfo.checkContext;
+                    Type pt = resultInfo.pt;
+                    if (inferenceContext.inferencevars.contains(pt)) {
+                        //ok
+                        return;
+                    } else {
+                        //must be a functional descriptor
+                        Type desc = types.findDescriptorType(pt);
+                        if (desc.getParameterTypes().length() != tree.params.length()) {
+                            checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
+                        }
+                    }
+                }
+
+                @Override
+                public void visitNewClass(JCNewClass tree) {
+                    //do nothing
+                }
+
+                @Override
+                public void visitApply(JCMethodInvocation tree) {
+                    //do nothing
+                }
+
+                @Override
+                public void visitReference(JCMemberReference tree) {
+                    //TODO: we should speculative determine if there's a match
+                    //based on arity - if yes, method is applicable.
+                }
             }
         }
     }
@@ -498,10 +583,80 @@
                 if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
             return List.nil();
         } else {
-            StuckChecker sc = new StuckChecker(resultInfo, env);
+            return stuckVarsInternal(tree, resultInfo.pt, resultInfo.checkContext.inferenceContext());
+        }
+    }
+    //where
+        private List<Type> stuckVarsInternal(JCTree tree, Type pt, Infer.InferenceContext inferenceContext) {
+            StuckChecker sc = new StuckChecker(pt, inferenceContext);
             sc.scan(tree);
             return List.from(sc.stuckVars);
         }
+    
+    /**
+     * A special tree scanner that would only visit portions of a given tree.
+     * The set of nodes visited by the scanner can be customized at construction-time.
+     */
+    abstract static class FilterScanner extends TreeScanner {
+        
+        final Filter<JCTree> treeFilter;
+
+        FilterScanner(final Set<JCTree.Tag> validTags) {
+            this.treeFilter = new Filter<JCTree>() {
+                public boolean accepts(JCTree t) {
+                    return validTags.contains(t.getTag());
+                }
+            };
+        }
+        
+        @Override
+        public void scan(JCTree tree) {
+            if (tree != null) {
+                if (treeFilter.accepts(tree)) {
+                    super.scan(tree);
+                } else {
+                    onDiscard(tree);
+                }
+            }
+        }
+        
+        /**
+         * handler that is executed when a node has been discarded
+         */
+        abstract void onDiscard(JCTree tree);
+    }
+    
+    /**
+     * A tree scanner suitable for visiting the target-type dependent nodes of
+     * a given argument expression.
+     */
+    static class PolyScanner extends FilterScanner {
+
+        PolyScanner() {
+            super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE));
+        }
+
+        @Override
+        void onDiscard(JCTree tree) {
+            //do nothing
+        }
+    }
+    
+    /**
+     * A tree scanner suitable for visiting the target-type dependent nodes nested
+     * within a lambda expression body.
+     */
+    static class LambdaReturnScanner extends FilterScanner {
+
+        LambdaReturnScanner() {
+            super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
+                    FORLOOP, RETURN, SYNCHRONIZED, SWITCH, TRY, WHILELOOP));
+        }
+        
+        @Override
+        void onDiscard(JCTree tree) {
+            //do nothing
+        }
     }
 
     /**
@@ -510,83 +665,32 @@
      * inferring types that make some of the nested expressions incompatible
      * with their corresponding instantiated target
      */
-    class StuckChecker extends TreeScanner {
+    class StuckChecker extends PolyScanner {
 
         Type pt;
-        Filter<JCTree> treeFilter;
         Infer.InferenceContext inferenceContext;
         Set<Type> stuckVars = new LinkedHashSet<Type>();
-        Env<AttrContext> env;
 
-        final Filter<JCTree> argsFilter = new Filter<JCTree>() {
-            public boolean accepts(JCTree t) {
-                switch (t.getTag()) {
-                    case CONDEXPR:
-                    case LAMBDA:
-                    case PARENS:
-                    case REFERENCE:
-                        return true;
-                    default:
-                        return false;
-                }
-            }
-        };
-
-        final Filter<JCTree> lambdaBodyFilter = new Filter<JCTree>() {
-            public boolean accepts(JCTree t) {
-                switch (t.getTag()) {
-                    case BLOCK: case CASE: case CATCH: case DOLOOP:
-                    case FOREACHLOOP: case FORLOOP: case RETURN:
-                    case SYNCHRONIZED: case SWITCH: case TRY: case WHILELOOP:
-                        return true;
-                    default:
-                        return false;
-                }
-            }
-        };
-
-        StuckChecker(ResultInfo resultInfo, Env<AttrContext> env) {
-            this.pt = resultInfo.pt;
-            this.inferenceContext = resultInfo.checkContext.inferenceContext();
-            this.treeFilter = argsFilter;
-            this.env = env;
-        }
-
-        @Override
-        public void scan(JCTree tree) {
-            if (tree != null && treeFilter.accepts(tree)) {
-                super.scan(tree);
-            }
+        StuckChecker(Type pt, Infer.InferenceContext inferenceContext) {
+            this.pt = pt;
+            this.inferenceContext = inferenceContext;
         }
 
         @Override
         public void visitLambda(JCLambda tree) {
-            Type prevPt = pt;
-            Filter<JCTree> prevFilter = treeFilter;
-            try {
-                if (inferenceContext.inferenceVars().contains(pt)) {
-                    stuckVars.add(pt);
-                }
-                if (!types.isFunctionalInterface(pt.tsym)) {
-                    return;
-                }
-                Type descType = types.findDescriptorType(pt);
-                List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
-                if (!TreeInfo.isExplicitLambda(tree) &&
-                        freeArgVars.nonEmpty()) {
-                    stuckVars.addAll(freeArgVars);
-                }
-                pt = descType.getReturnType();
-                if (tree.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
-                    scan(tree.getBody());
-                } else {
-                    treeFilter = lambdaBodyFilter;
-                    super.visitLambda(tree);
-                }
-            } finally {
-                pt = prevPt;
-                treeFilter = prevFilter;
+            if (inferenceContext.inferenceVars().contains(pt)) {
+                stuckVars.add(pt);
             }
+            if (!types.isFunctionalInterface(pt.tsym)) {
+                return;
+            }
+            Type descType = types.findDescriptorType(pt);
+            List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
+            if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
+                    freeArgVars.nonEmpty()) {
+                stuckVars.addAll(freeArgVars);
+            }
+            scanLambdaBody(tree, descType.getReturnType());
         }
 
         @Override
@@ -604,17 +708,20 @@
             List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
             stuckVars.addAll(freeArgVars);
         }
-
-        @Override
-        public void visitReturn(JCReturn tree) {
-            Filter<JCTree> prevFilter = treeFilter;
-            try {
-                treeFilter = argsFilter;
-                if (tree.expr != null) {
-                    scan(tree.expr);
-                }
-            } finally {
-                treeFilter = prevFilter;
+        
+        void scanLambdaBody(JCLambda lambda, final Type pt) {
+            if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
+                stuckVars.addAll(stuckVarsInternal(lambda.body, pt, inferenceContext));
+            } else {
+                LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
+                    @Override
+                    public void visitReturn(JCReturn tree) {
+                        if (tree.expr != null) {
+                            stuckVars.addAll(stuckVarsInternal(tree.expr, pt, inferenceContext));
+                        }
+                    }
+                };
+                lambdaScanner.scan(lambda.body);
             }
         }
     }
--- a/src/share/classes/com/sun/tools/javac/comp/GraphInfer.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/GraphInfer.java	Mon Dec 17 15:36:20 2012 +0000
@@ -84,14 +84,17 @@
                                   boolean allowBoxing,
                                   boolean useVarargs,
                                   Resolve.MethodResolutionContext resolveContext,
-                                  Warner warn) throws InferenceException {
+                                  Warner warn,
+                                  Resolve.MethodCheck methodCheck) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
         final GraphInferenceContext inferenceContext = new GraphInferenceContext(tvars);
         inferenceException.clear();
         try {
-            rs.checkRawArgumentsAcceptable(env, msym, resolveContext.attrMode(), inferenceContext,
-                    argtypes, mt.getParameterTypes(), allowBoxing, useVarargs, warn,
-                    new InferenceCheckHandler(inferenceContext));
+            DeferredAttr.DeferredAttrContext deferredAttrContext =
+                    resolveContext.deferredAttrContext(msym, inferenceContext);
+            
+            methodCheck.argumentsAcceptable(env, deferredAttrContext,
+                    argtypes, mt.getParameterTypes(), warn);
 
             if (resultInfo != null &&
                     !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
@@ -111,6 +114,8 @@
                     return mt;
                 }
             }
+            
+            deferredAttrContext.complete();
 
             // minimize as yet undetermined type variables
             inferenceContext.solve();
--- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Dec 17 15:36:20 2012 +0000
@@ -112,7 +112,8 @@
                                   boolean allowBoxing,
                                   boolean useVarargs,
                                   Resolve.MethodResolutionContext resolveContext,
-                                  Warner warn) throws InferenceException;
+                                  Warner warn,
+                                  Resolve.MethodCheck methodCheck) throws InferenceException;
 
     /**
      * This method is used to infer a suitable target SAM in case the original
@@ -129,34 +130,6 @@
             return !t.isErroneous() && !t.hasTag(BOT);
         }
     };
-
-    /** 
-     * Inference check handler - used to report inference error during method
-     * instantiation (see Infer.intantiateMethod).
-     */
-    class InferenceCheckHandler implements Resolve.MethodCheckHandler {
-
-        InferenceContext inferenceContext;
-
-        public InferenceCheckHandler(InferenceContext inferenceContext) {
-            this.inferenceContext = inferenceContext;
-        }
-
-        public InapplicableMethodException arityMismatch() {
-            return inferenceException.setMessage("infer.arg.length.mismatch", inferenceContext.inferenceVars());
-        }
-        public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
-            String key = varargs ?
-                    "infer.varargs.argument.mismatch" :
-                    "infer.no.conforming.assignment.exists";
-            return inferenceException.setMessage(key,
-                    inferenceContext.inferenceVars(), details);
-        }
-        public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
-            return inferenceException.setMessage("inaccessible.varargs.type",
-                    expected, Kinds.kindName(location), location);
-        }
-    }
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Bound checking">
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Mon Dec 17 15:36:20 2012 +0000
@@ -43,7 +43,6 @@
 import com.sun.tools.javac.code.Type.ClassType;
 import com.sun.tools.javac.code.Type.MethodType;
 import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.comp.Attr.FunctionalInfo;
 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzer.*;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.util.*;
@@ -125,7 +124,7 @@
         
         private KlassInfo(Symbol kSym) {
             appendedMethodList = ListBuffer.lb();
-            deserializeCases = new HashMap<>();
+            deserializeCases = new HashMap<String, ListBuffer<JCStatement>>();
             long flags = PRIVATE | STATIC | SYNTHETIC;
             MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType,
                     List.<Type>nil(), syms.methodClass);
@@ -303,7 +302,7 @@
         int refKind = referenceKind(sym);
 
         //convert to an invokedynamic call
-        result = makeMetaFactoryIndyCall(tree, tree.fInfo, refKind, sym, indy_args);
+        result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args);
     }
 
     private JCIdent makeThis(Type type, Symbol owner) {
@@ -363,7 +362,7 @@
 
 
         //build a sam instance using an indy call to the meta-factory
-        result = makeMetaFactoryIndyCall(tree, tree.fInfo, localContext.referenceKind(), refSym, indy_args);
+        result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args);
     }
 
     /**
@@ -651,19 +650,6 @@
 
     // </editor-fold>
 
-    private MethodSymbol makeSamDescriptor(Type targetType) {
-        return (MethodSymbol)types.findDescriptorSymbol(targetType.tsym);
-    }
-
-    private Type makeFunctionalDescriptorType(Type targetType, MethodSymbol samDescriptor, boolean erased) {
-        Type descType = types.memberType(targetType, samDescriptor);
-        return erased ? types.erasure(descType) : descType;
-    }
-
-    private Type makeFunctionalDescriptorType(Type targetType, boolean erased) {
-        return makeFunctionalDescriptorType(targetType, makeSamDescriptor(targetType), erased);
-    }
-
     /**
      * Generate an adapter method "bridge" for a method reference which cannot
      * be used directly.
@@ -836,21 +822,19 @@
     /**
      * Generate an indy method call to the meta factory
      */
-    private JCExpression makeMetaFactoryIndyCall(JCExpression tree, FunctionalInfo fInfo, int refKind, Symbol refSym, List<JCExpression> indy_args) {
+    private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory,
+            boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) {
         //determine the static bsm args
-        Type mtype = makeFunctionalDescriptorType(fInfo.targetType, true);
-        MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(fInfo.targetType.tsym);
+        Type mtype = types.erasure(tree.descriptorType);
+        MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
         List<Object> staticArgs = List.<Object>of(
-                new Pool.MethodHandle(ClassFile.REF_invokeInterface, samSym),
+                new Pool.MethodHandle(ClassFile.REF_invokeInterface, types.findDescriptorSymbol(tree.type.tsym)),
                 new Pool.MethodHandle(refKind, refSym),
                 new MethodType(mtype.getParameterTypes(),
                         mtype.getReturnType(),
                         mtype.getThrownTypes(),
                         syms.methodClass));
         
-        boolean altMetafactory =
-                fInfo.isSerializable || fInfo.targets.tail.nonEmpty();
-        
         //computed indy arg types
         ListBuffer<Type> indy_args_types = ListBuffer.lb();
         for (JCExpression arg : indy_args) {
@@ -863,22 +847,22 @@
                 List.<Type>nil(),
                 syms.methodClass);
         
-        Name metafactoryName = altMetafactory ?
+        Name metafactoryName = needsAltMetafactory ?
                 names.altMetaFactory : names.metaFactory;
 
-        if (altMetafactory) {
-            int flags = fInfo.isSerializable ? FLAG_SERIALIZABLE : 0;
+        if (needsAltMetafactory) {
+            int flags = isSerializable? FLAG_SERIALIZABLE : 0;
             staticArgs = staticArgs.append(flags);
-            for (Symbol t : fInfo.targets.tail) {
+            for (Symbol t : tree.targets.tail) {
                 staticArgs = staticArgs.append(t);
             }
-            addDeserializationCase(refKind, refSym, fInfo.targetType, samSym, 
+            addDeserializationCase(refKind, refSym, tree.type, samSym, 
                     tree, staticArgs, indyType);
         }
 
         return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args);
     }
-    
+
     /**
      * Generate an indy method call with given name, type and static bootstrap
      * arguments types
@@ -1319,7 +1303,7 @@
          * This class is used to store important information regarding translation of
          * lambda expression/method references (see subclasses).
          */
-        private abstract class TranslationContext<T extends JCTree> {
+        private abstract class TranslationContext<T extends JCFunctionalExpression> {
 
             /** the underlying (untranslated) tree */
             T tree;
@@ -1339,6 +1323,22 @@
                 this.depth = frameStack.size() - 1;
                 this.prev = context();
             }
+            
+            /** does this functional expression need to be created using alternate metafactory? */
+            boolean needsAltMetafactory() {
+                return (tree.targets.length() > 1 ||
+                        isSerializable());
+            }
+            
+            /** does this functional expression require serialization support? */
+            boolean isSerializable() {
+                for (Symbol target : tree.targets) {
+                    if (types.asSuper(target.type, syms.serializableType.tsym) != null) {
+                        return true;
+                    }
+                }
+                return false;
+            }
         }
 
         /**
@@ -1483,7 +1483,7 @@
             }
 
             Type generatedLambdaSig() {
-                return types.erasure(types.findDescriptorType(tree.fInfo.targetType));
+                return types.erasure(tree.descriptorType);
             }
         }
 
@@ -1539,7 +1539,7 @@
             }
 
             Type bridgedRefSig() {
-                return types.erasure(types.findDescriptorSymbol(tree.fInfo.targetType.tsym).type);
+                return types.erasure(types.findDescriptorSymbol(tree.type.tsym).type);
             }
         }
     }
--- a/src/share/classes/com/sun/tools/javac/comp/LegacyInfer.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/LegacyInfer.java	Mon Dec 17 15:36:20 2012 +0000
@@ -48,12 +48,15 @@
     Check chk;
     Resolve rs;
     Log log;
+    
+    boolean allowBetterInference;
 
     protected LegacyInfer(Context context) {
         super(context);
         rs = Resolve.instance(context);
         log = Log.instance(context);
         chk = Check.instance(context);
+        allowBetterInference = Source.instance(context).allowBetterInference();
     }
 
 /***************************************************************************
@@ -120,19 +123,6 @@
             MethodType mtype,
             Attr.ResultInfo resultInfo,
             Warner warn) throws InferenceException {
-        Type to = resultInfo.pt;
-        if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
-             to = mtype.getReturnType().isPrimitiveOrVoid() ?
-                     mtype.getReturnType() : syms.objectType;
-        }
-        Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types);
-        if (!types.isSubtype(qtype1,
-                qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) {
-            throw inferenceException
-                    .setMessage("infer.no.conforming.instance.exists",
-                    inferenceContext.restvars(), mtype.getReturnType(), to);
-        }
-
         while (true) {
             boolean stuck = true;
             for (Type t : inferenceContext.undetvars) {
@@ -201,15 +191,25 @@
                                   boolean allowBoxing,
                                   boolean useVarargs,
                                   Resolve.MethodResolutionContext resolveContext,
-                                  Warner warn) throws InferenceException {
+                                  Warner warn,
+                                  Resolve.MethodCheck methodCheck) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
         final InferenceContext inferenceContext = new LegacyInferenceContext(tvars, true);
         inferenceException.clear();
 
         try {
-            rs.checkRawArgumentsAcceptable(env, msym, resolveContext.attrMode(), inferenceContext,
-                    argtypes, mt.getParameterTypes(), allowBoxing, useVarargs, warn,
-                    new InferenceCheckHandler(inferenceContext));
+            DeferredAttr.DeferredAttrContext deferredAttrContext =
+                    resolveContext.deferredAttrContext(msym, inferenceContext);
+            
+            methodCheck.argumentsAcceptable(env, deferredAttrContext,
+                    argtypes, mt.getParameterTypes(), warn);
+            
+            if (resultInfo != null && allowBetterInference &&
+                    !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
+                generateReturnConstraints(mt, inferenceContext, resultInfo);
+            }
+            
+            deferredAttrContext.complete();
 
             // minimize as yet undetermined type variables
             for (Type t : inferenceContext.undetvars) {
@@ -224,6 +224,9 @@
 
             if (!restvars.isEmpty()) {
                 if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
+                    if (!allowBetterInference) {
+                        generateReturnConstraints(mt, inferenceContext, resultInfo);
+                    }
                     instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
                     checkWithinBounds(inferenceContext, warn);
                     mt = (MethodType)inferenceContext.asInstType(mt, types);
@@ -240,6 +243,23 @@
         }
     }
     
+    void generateReturnConstraints(Type mt, InferenceContext inferenceContext, Attr.ResultInfo resultInfo) {
+        if (resultInfo != null) {
+            Type to = resultInfo.pt;
+            if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
+                to = mt.getReturnType().isPrimitiveOrVoid() ?
+                        mt.getReturnType() : syms.objectType;
+            }
+            Type qtype1 = inferenceContext.asFree(mt.getReturnType(), types);
+            if (!types.isSubtype(qtype1,
+                    qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) {
+                throw inferenceException
+                        .setMessage("infer.no.conforming.instance.exists",
+                        inferenceContext.restvars(), mt.getReturnType(), to);
+            }
+        }
+    }
+    
     @Override
     public Type instantiateFunctionalInterface(DiagnosticPosition pos, Type funcInterface,
             List<Type> paramTypes, Check.CheckContext checkContext) {
@@ -251,52 +271,40 @@
             Type formalInterface = funcInterface.tsym.type;
             InferenceContext funcInterfaceContext =
                     new LegacyInferenceContext(funcInterface.tsym.type.getTypeArguments(), false);
-            if (paramTypes != null) {
-                //get constraints from explicit params (this is done by
-                //checking that explicit param types are equal to the ones
-                //in the functional interface descriptors)
-                List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
-                if (descParameterTypes.size() != paramTypes.size()) {
-                    checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
+            Assert.check(paramTypes != null);
+            //get constraints from explicit params (this is done by
+            //checking that explicit param types are equal to the ones
+            //in the functional interface descriptors)
+            List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
+            if (descParameterTypes.size() != paramTypes.size()) {
+                checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
+                return types.createErrorType(funcInterface);
+            }
+            for (Type p : descParameterTypes) {
+                if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
+                    checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
                     return types.createErrorType(funcInterface);
                 }
-                for (Type p : descParameterTypes) {
-                    if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
-                        checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
-                        return types.createErrorType(funcInterface);
-                    }
-                    paramTypes = paramTypes.tail;
+                paramTypes = paramTypes.tail;
+            }
+            List<Type> actualTypeargs = funcInterface.getTypeArguments();
+            for (Type t : funcInterfaceContext.undetvars) {
+                UndetVar uv = (UndetVar)t;
+                minimizeInst(uv, funcInterfaceContext);
+                if (uv.inst == null &&
+                        Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
+                    maximizeInst(uv, funcInterfaceContext);
                 }
-                for (Type t : funcInterfaceContext.undetvars) {
-                    UndetVar uv = (UndetVar)t;
-                    minimizeInst(uv, funcInterfaceContext);
-                    if (uv.inst == null &&
-                            Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
-                        maximizeInst(uv, funcInterfaceContext);
-                    }
-                }
-
-                formalInterface = funcInterfaceContext.asInstType(formalInterface, types);
-            }
-            ListBuffer<Type> typeargs = ListBuffer.lb();
-            List<Type> actualTypeargs = funcInterface.getTypeArguments();
-            //for remaining uninferred type-vars in the functional interface type,
-            //simply replace the wildcards with its bound
-            for (Type t : formalInterface.getTypeArguments()) {
-                if (actualTypeargs.head.hasTag(WILDCARD)) {
-                    WildcardType wt = (WildcardType)actualTypeargs.head;
-                    typeargs.append(wt.type);
-                } else {
-                    typeargs.append(actualTypeargs.head);
+                if (uv.inst == null) {
+                    uv.inst = actualTypeargs.head;
                 }
                 actualTypeargs = actualTypeargs.tail;
             }
-            Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList());
+            Type owntype = funcInterfaceContext.asInstType(formalInterface, types);
             if (!chk.checkValidGenericType(owntype)) {
                 //if the inferred functional interface type is not well-formed,
                 //or if it's not a subtype of the original target, issue an error
                 checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
-                return types.createErrorType(funcInterface);
             }
             return owntype;
         }
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Dec 17 15:36:20 2012 +0000
@@ -92,6 +92,7 @@
     public final boolean varargsEnabled; // = source.allowVarargs();
     public final boolean allowMethodHandles;
     public final boolean allowDefaultMethods;
+    public final boolean allowStructuralMostSpecific;
     private final boolean debugResolve;
     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
 
@@ -127,6 +128,7 @@
         Target target = Target.instance(context);
         allowMethodHandles = target.hasMethodHandles();
         allowDefaultMethods = source.allowDefaultMethods();
+        allowStructuralMostSpecific = source.allowStructuralMostSpecific();
         polymorphicSignatureScope = new Scope(syms.noSymbol);
 
         inapplicableMethodException = new InapplicableMethodException(diags);
@@ -506,7 +508,8 @@
                         List<Type> typeargtypes,
                         boolean allowBoxing,
                         boolean useVarargs,
-                        Warner warn) throws Infer.InferenceException {
+                        Warner warn,
+                        MethodCheck methodCheck) throws Infer.InferenceException {
 
         Type mt = types.memberType(site, m);
         // tvars is the list of formal type variables for which type arguments
@@ -558,10 +561,11 @@
                                     allowBoxing,
                                     useVarargs,
                                     currentResolutionContext,
-                                    warn);
-
-        checkRawArgumentsAcceptable(env, m, argtypes, mt.getParameterTypes(),
-                                allowBoxing, useVarargs, warn);
+                                    warn,
+                                    methodCheck);
+
+        methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext),
+                                argtypes, mt.getParameterTypes(), warn);
         return mt;
     }
 
@@ -578,7 +582,7 @@
             currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK;
             MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase;
             return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
-                    step.isBoxingRequired(), step.isVarargsRequired(), warn);
+                    step.isBoxingRequired(), step.isVarargsRequired(), warn, resolveMethodCheck);
         }
         finally {
             currentResolutionContext = prevContext;
@@ -595,81 +599,66 @@
                      List<Type> typeargtypes,
                      boolean allowBoxing,
                      boolean useVarargs,
-                     Warner warn) {
+                     Warner warn,
+                     MethodCheck methodCheck) {
         try {
             return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
-                                  allowBoxing, useVarargs, warn);
+                                  allowBoxing, useVarargs, warn, methodCheck);
         } catch (InapplicableMethodException ex) {
             return null;
         }
     }
-
-    /** Check if a parameter list accepts a list of args.
+    
+    /**
+     * This interface defines an entry point that should be used to perform a
+     * method check. A method check usually consist in determining as to whether
+     * a set of types (actuals) is compatible with another set of types (formals).
+     * Since the notion of compatibility can vary depending on the circumstances,
+     * this interfaces allows to easily add new pluggable method check routines.
      */
-    boolean argumentsAcceptable(Env<AttrContext> env,
-                                Symbol msym,
+    interface MethodCheck {
+        /**
+         * Main method check routine. A method check usually consist in determining
+         * as to whether a set of types (actuals) is compatible with another set of
+         * types (formals). If an incompatibility is found, an unchecked exception
+         * is assumed to be thrown.
+         */
+        void argumentsAcceptable(Env<AttrContext> env,
+                                DeferredAttrContext deferredAttrContext,
                                 List<Type> argtypes,
                                 List<Type> formals,
-                                boolean allowBoxing,
-                                boolean useVarargs,
-                                Warner warn) {
-        try {
-            checkRawArgumentsAcceptable(env, msym, argtypes, formals, allowBoxing, useVarargs, warn);
-            return true;
-        } catch (InapplicableMethodException ex) {
-            return false;
+                                Warner warn);
+    }
+    
+    /**
+     * Helper enum defining all method check diagnostics (used by resolveMethodCheck).
+     */
+    enum MethodCheckDiag {
+        /**
+         * Actuals and formals differs in length.
+         */
+        ARITY_MISMATCH("arg.length.mismatch", "infer.arg.length.mismatch"),
+        /**
+         * An actual is incompatible with a formal.
+         */
+        ARG_MISMATCH("no.conforming.assignment.exists", "infer.no.conforming.assignment.exists"),
+        /**
+         * An actual is incompatible with the varargs element type.
+         */
+        VARARG_MISMATCH("varargs.argument.mismatch", "infer.varargs.argument.mismatch"),
+        /**
+         * The varargs element type is inaccessible.
+         */
+        INACCESSIBLE_VARARGS("inaccessible.varargs.type", "inaccessible.varargs.type");
+        
+        String basicKey;
+        String inferKey;
+
+        MethodCheckDiag(String basicKey, String inferKey) {
+            this.basicKey = basicKey;
+            this.inferKey = inferKey;
         }
     }
-    /**
-     * A check handler is used by the main method applicability routine in order
-     * to handle specific method applicability failures. It is assumed that a class
-     * implementing this interface should throw exceptions that are a subtype of
-     * InapplicableMethodException (see below). Such exception will terminate the
-     * method applicability check and propagate important info outwards (for the
-     * purpose of generating better diagnostics).
-     */
-    interface MethodCheckHandler {
-        /* The number of actuals and formals differ */
-        InapplicableMethodException arityMismatch();
-        /* An actual argument type does not conform to the corresponding formal type */
-        InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details);
-        /* The element type of a varargs is not accessible in the current context */
-        InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected);
-    }
-
-    /**
-     * Basic method check handler used within Resolve - all methods end up
-     * throwing InapplicableMethodException; a diagnostic fragment that describes
-     * the cause as to why the method is not applicable is set on the exception
-     * before it is thrown.
-     */
-    MethodCheckHandler resolveHandler = new MethodCheckHandler() {
-            public InapplicableMethodException arityMismatch() {
-                return inapplicableMethodException.setMessage("arg.length.mismatch");
-            }
-            public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
-                String key = varargs ?
-                        "varargs.argument.mismatch" :
-                        "no.conforming.assignment.exists";
-                return inapplicableMethodException.setMessage(key,
-                        details);
-            }
-            public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
-                return inapplicableMethodException.setMessage("inaccessible.varargs.type",
-                        expected, Kinds.kindName(location), location);
-            }
-    };
-
-    void checkRawArgumentsAcceptable(Env<AttrContext> env,
-                                Symbol msym,
-                                List<Type> argtypes,
-                                List<Type> formals,
-                                boolean allowBoxing,
-                                boolean useVarargs,
-                                Warner warn) {
-        checkRawArgumentsAcceptable(env, msym, currentResolutionContext.attrMode(), infer.emptyContext, argtypes, formals,
-                allowBoxing, useVarargs, warn, resolveHandler);
-    }
 
     /**
      * Main method applicability routine. Given a list of actual types A,
@@ -689,92 +678,119 @@
      *
      * A method check handler (see above) is used in order to report errors.
      */
-    void checkRawArgumentsAcceptable(final Env<AttrContext> env,
-                                Symbol msym,
-                                DeferredAttr.AttrMode mode,
-                                final Infer.InferenceContext inferenceContext,
-                                List<Type> argtypes,
-                                List<Type> formals,
-                                boolean allowBoxing,
-                                boolean useVarargs,
-                                Warner warn,
-                                final MethodCheckHandler handler) {
-        Type varargsFormal = useVarargs ? formals.last() : null;
-
-        if (varargsFormal == null &&
-                argtypes.size() != formals.size()) {
-            throw handler.arityMismatch(); // not enough args
-        }
-
-        DeferredAttr.DeferredAttrContext deferredAttrContext =
-                deferredAttr.new DeferredAttrContext(mode, msym, currentResolutionContext.step, inferenceContext);
-
-        while (argtypes.nonEmpty() && formals.head != varargsFormal) {
-            ResultInfo mresult = methodCheckResult(formals.head, allowBoxing, false, inferenceContext, deferredAttrContext, handler, warn);
-            mresult.check(null, argtypes.head);
-            argtypes = argtypes.tail;
-            formals = formals.tail;
-        }
-
-        if (formals.head != varargsFormal) {
-            throw handler.arityMismatch(); // not enough args
-        }
-
-        if (useVarargs) {
-            //note: if applicability check is triggered by most specific test,
-            //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
-            final Type elt = types.elemtype(varargsFormal);
-            ResultInfo mresult = methodCheckResult(elt, allowBoxing, true, inferenceContext, deferredAttrContext, handler, warn);
-            while (argtypes.nonEmpty()) {
+    MethodCheck resolveMethodCheck = new MethodCheck() {
+        @Override
+        public void argumentsAcceptable(final Env<AttrContext> env,
+                                    DeferredAttrContext deferredAttrContext,
+                                    List<Type> argtypes,
+                                    List<Type> formals,
+                                    Warner warn) {
+            //should we expand formals?
+            boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
+            
+            //inference context used during this method check
+            InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
+            
+            Type varargsFormal = useVarargs ? formals.last() : null;
+
+            if (varargsFormal == null &&
+                    argtypes.size() != formals.size()) {
+                report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+            }
+
+            while (argtypes.nonEmpty() && formals.head != varargsFormal) {
+                ResultInfo mresult = methodCheckResult(false, formals.head, deferredAttrContext, warn);
                 mresult.check(null, argtypes.head);
                 argtypes = argtypes.tail;
+                formals = formals.tail;
             }
-            //check varargs element type accessibility
-            varargsAccessible(env, elt, handler, inferenceContext);
-        }
-
-        deferredAttrContext.complete();
-    }
-
-    void varargsAccessible(final Env<AttrContext> env, final Type t, final Resolve.MethodCheckHandler handler, final InferenceContext inferenceContext) {
-        if (inferenceContext.free(t)) {
-            inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
-                @Override
-                public void typesInferred(InferenceContext inferenceContext) {
-                    varargsAccessible(env, inferenceContext.asInstType(t, types), handler, inferenceContext);
+
+            if (formals.head != varargsFormal) {
+                report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+            }
+
+            if (useVarargs) {
+                //note: if applicability check is triggered by most specific test,
+                //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
+                final Type elt = types.elemtype(varargsFormal);
+                ResultInfo mresult = methodCheckResult(true, elt, deferredAttrContext, warn);
+                while (argtypes.nonEmpty()) {
+                    mresult.check(null, argtypes.head);
+                    argtypes = argtypes.tail;
                 }
-            });
-        } else {
-            if (!isAccessible(env, t)) {
-                Symbol location = env.enclClass.sym;
-                throw handler.inaccessibleVarargs(location, t);
+                //check varargs element type accessibility
+                varargsAccessible(env, elt, inferenceContext);
             }
         }
-    }
-
+        
+        private void report(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
+            boolean inferDiag = inferenceContext != infer.emptyContext;
+            InapplicableMethodException ex = inferDiag ?
+                    infer.inferenceException : inapplicableMethodException;
+            if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
+                Object[] args2 = new Object[args.length + 1];
+                System.arraycopy(args, 0, args2, 1, args.length);
+                args2[0] = inferenceContext.inferenceVars();
+                args = args2;
+            }
+            throw ex.setMessage(inferDiag ? diag.inferKey : diag.basicKey, args);
+        }
+        
+        private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) {
+            if (inferenceContext.free(t)) {
+                inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
+                    @Override
+                    public void typesInferred(InferenceContext inferenceContext) {
+                        varargsAccessible(env, inferenceContext.asInstType(t, types), inferenceContext);
+                    }
+                });
+            } else {
+                if (!isAccessible(env, t)) {
+                    Symbol location = env.enclClass.sym;
+                    report(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
+                }
+            }
+        }
+
+        private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
+                final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) {
+            CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) {
+                MethodCheckDiag methodDiag = varargsCheck ?
+                                 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
+                        
+                @Override
+                public void report(DiagnosticPosition pos, JCDiagnostic details) {
+                    report(methodDiag, deferredAttrContext.inferenceContext, details);
+                }
+            };
+            return new MethodResultInfo(to, checkContext);
+        }
+    };
+    
     /**
      * Check context to be used during method applicability checks. A method check
      * context might contain inference variables.
      */
     abstract class MethodCheckContext implements CheckContext {
-
-        MethodCheckHandler handler;
-        boolean useVarargs;
-        Infer.InferenceContext inferenceContext;
+           
+        boolean strict;
         DeferredAttrContext deferredAttrContext;
-        Warner rsWarner;
-
-        public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs,
-                Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
-            this.handler = handler;
-            this.useVarargs = useVarargs;
-            this.inferenceContext = inferenceContext;
-            this.deferredAttrContext = deferredAttrContext;
-            this.rsWarner = rsWarner;
+        Warner rsWarner;        
+
+        public MethodCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
+           this.strict = strict;
+           this.deferredAttrContext = deferredAttrContext;
+           this.rsWarner = rsWarner;
         }
+        
+        public boolean compatible(Type found, Type req, Warner warn) {
+            return strict ?
+                    types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asFree(req, types), warn) :
+                    types.isConvertible(found, deferredAttrContext.inferenceContext.asFree(req, types), warn);
+        }
 
         public void report(DiagnosticPosition pos, JCDiagnostic details) {
-            throw handler.argumentMismatch(useVarargs, details);
+            throw inapplicableMethodException.setMessage(details);               
         }
 
         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
@@ -782,7 +798,7 @@
         }
 
         public InferenceContext inferenceContext() {
-            return inferenceContext;
+            return deferredAttrContext.inferenceContext;
         }
 
         public DeferredAttrContext deferredAttrContext() {
@@ -791,56 +807,13 @@
     }
 
     /**
-     * Subclass of method check context class that implements strict method conversion.
-     * Strict method conversion checks compatibility between types using subtyping tests.
+     * ResultInfo class to be used during method applicability checks. Check
+     * for deferred types goes through special path.
      */
-    class StrictMethodContext extends MethodCheckContext {
-
-        public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs,
-                Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
-            super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
-        }
-
-        public boolean compatible(Type found, Type req, Warner warn) {
-            return types.isSubtypeUnchecked(found, inferenceContext.asFree(req, types), warn);
-        }
-    }
-
-    /**
-     * Subclass of method check context class that implements loose method conversion.
-     * Loose method conversion checks compatibility between types using method conversion tests.
-     */
-    class LooseMethodContext extends MethodCheckContext {
-
-        public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs,
-                Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
-            super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
-        }
-
-        public boolean compatible(Type found, Type req, Warner warn) {
-            return types.isConvertible(found, inferenceContext.asFree(req, types), warn);
-        }
-    }
-
-    /**
-     * Create a method check context to be used during method applicability check
-     */
-    ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs,
-            Infer.InferenceContext inferenceContext, DeferredAttr.DeferredAttrContext deferredAttrContext,
-            MethodCheckHandler methodHandler, Warner rsWarner) {
-        MethodCheckContext checkContext = allowBoxing ?
-                new LooseMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner) :
-                new StrictMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
-        return new MethodResultInfo(to, checkContext, deferredAttrContext);
-    }
-
     class MethodResultInfo extends ResultInfo {
 
-        DeferredAttr.DeferredAttrContext deferredAttrContext;
-
-        public MethodResultInfo(Type pt, CheckContext checkContext, DeferredAttr.DeferredAttrContext deferredAttrContext) {
+        public MethodResultInfo(Type pt, CheckContext checkContext) {
             attr.super(VAL, pt, checkContext);
-            this.deferredAttrContext = deferredAttrContext;
         }
 
         @Override
@@ -855,12 +828,211 @@
 
         @Override
         protected MethodResultInfo dup(Type newPt) {
-            return new MethodResultInfo(newPt, checkContext, deferredAttrContext);
+            return new MethodResultInfo(newPt, checkContext);
         }
 
         @Override
         protected ResultInfo dup(CheckContext newContext) {
-            return new MethodResultInfo(pt, newContext, deferredAttrContext);
+            return new MethodResultInfo(pt, newContext);
+        }
+    }    
+
+    /**
+     * Most specific method applicability routine. Given a list of actual types A,
+     * a list of formal types F1, and a list of formal types F2, the routine determines
+     * as to whether the types in F1 can be considered more specific than those in F2 w.r.t.
+     * argument types A.
+     */
+    class MostSpecificCheck implements MethodCheck {
+        
+        boolean strict;
+        List<Type> actuals;
+
+        MostSpecificCheck(boolean strict, List<Type> actuals) {
+            this.strict = strict;
+            this.actuals = actuals;
+        }
+        
+        @Override
+        public void argumentsAcceptable(final Env<AttrContext> env,
+                                    DeferredAttrContext deferredAttrContext,
+                                    List<Type> formals1,
+                                    List<Type> formals2,
+                                    Warner warn) {
+            formals2 = adjustArgs(formals2, deferredAttrContext.msym, formals1.length(), deferredAttrContext.phase.isVarargsRequired());
+            while (formals2.nonEmpty()) {
+                ResultInfo mresult = methodCheckResult(formals2.head, deferredAttrContext, warn, actuals.head);
+                mresult.check(null, formals1.head);
+                formals1 = formals1.tail;
+                formals2 = formals2.tail;
+                actuals = actuals.isEmpty() ? actuals : actuals.tail;
+            }
+        }
+        
+       /**
+        * Create a method check context to be used during the most specific applicability check
+        */
+        ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext,
+               Warner rsWarner, Type actual) {
+           return attr.new ResultInfo(Kinds.VAL, to,
+                   new MostSpecificCheckContext(strict, deferredAttrContext, rsWarner, actual));
+        }
+       
+        /**
+         * Subclass of method check context class that implements most specific
+         * method conversion. If the actual type under analysis is a deferred type
+         * a full blown structural analysis is carried out.
+         */
+        class MostSpecificCheckContext extends MethodCheckContext {
+            
+            Type actual;
+
+            public MostSpecificCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) {
+                super(strict, deferredAttrContext, rsWarner);
+                this.actual = actual;
+            }
+
+            public boolean compatible(Type found, Type req, Warner warn) {
+                if (!allowStructuralMostSpecific || actual == null) {
+                    return super.compatible(found, req, warn);
+                } else {
+                    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);
+                        default:
+                            return standaloneMostSpecific(found, req, actual, warn);
+                    }
+                }
+            }
+
+            private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) {
+                MostSpecificChecker msc = new MostSpecificChecker(t, s, warn);
+                msc.scan(tree);
+                return msc.result;
+            }
+
+            boolean polyMostSpecific(Type t1, Type t2, Warner warn) {
+                return (!t1.isPrimitive() && t2.isPrimitive())
+                        ? true : super.compatible(t1, t2, warn);
+            }
+
+            boolean standaloneMostSpecific(Type t1, Type t2, Type exprType, Warner warn) {
+                return (exprType.isPrimitive() == t1.isPrimitive()
+                        && exprType.isPrimitive() != t2.isPrimitive())
+                        ? true : super.compatible(t1, t2, warn);
+            }
+
+            /**
+             * Structural checker for most specific.
+             */
+            class MostSpecificChecker extends DeferredAttr.PolyScanner {
+
+                final Type t;
+                final Type s;
+                final Warner warn;
+                boolean result;
+
+                MostSpecificChecker(Type t, Type s, Warner warn) {
+                    this.t = t;
+                    this.s = s;
+                    this.warn = warn;
+                    result = true;
+                }
+
+                @Override
+                void onDiscard(JCTree tree) {
+                    result &= standaloneMostSpecific(t, s, tree.type, warn);
+                }
+
+                @Override
+                public void visitConditional(JCConditional tree) {
+                    if (tree.polyKind == PolyKind.STANDALONE) {
+                        result &= standaloneMostSpecific(t, s, tree.type, warn);
+                    } else {
+                        super.visitConditional(tree);
+                    }
+                }
+
+                @Override
+                public void visitApply(JCMethodInvocation tree) {
+                    result &= (tree.polyKind == PolyKind.STANDALONE)
+                            ? standaloneMostSpecific(t, s, tree.type, warn)
+                            : polyMostSpecific(t, s, warn);
+                }
+
+                @Override
+                public void visitNewClass(JCNewClass tree) {
+                    result &= (tree.polyKind == PolyKind.STANDALONE)
+                            ? standaloneMostSpecific(t, s, tree.type, warn)
+                            : polyMostSpecific(t, s, warn);
+                }
+
+                @Override
+                public void visitReference(JCMemberReference tree) {
+                    //TODO: subtyping shoukd take precedence over structural
+                    //check - fix this when libraries are fixed
+                    if (types.isFunctionalInterface(t.tsym)
+                            && types.isFunctionalInterface(s.tsym)) {
+                        Type desc_t = types.findDescriptorType(t);
+                        Type desc_s = types.findDescriptorType(s);
+                        if (types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
+                            if (!desc_s.getReturnType().hasTag(VOID)) {
+                                //perform structural comparison
+                                Type ret_t = desc_t.getReturnType();
+                                Type ret_s = desc_s.getReturnType();
+                                result &= ((tree.polyKind == PolyKind.STANDALONE)
+                                        ? standaloneMostSpecific(ret_t, ret_s, tree.type, warn)
+                                        : polyMostSpecific(ret_t, ret_s, warn));
+                            }
+                            return;
+                        }
+                    }
+                    result &= MostSpecificCheckContext.super.compatible(t, s, warn);
+                }
+
+                @Override
+                public void visitLambda(JCLambda tree) {
+                    //TODO: subtyping shoukd take precedence over structural
+                    //check - fix this when libraries are fixed
+                    if (types.isFunctionalInterface(t.tsym)
+                            && types.isFunctionalInterface(s.tsym)) {
+                        Type desc_t = types.findDescriptorType(t);
+                        Type desc_s = types.findDescriptorType(s);
+                        if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT
+                                || types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
+                            if (!desc_s.getReturnType().hasTag(VOID)) {
+                                //perform structural comparison
+                                Type ret_t = desc_t.getReturnType();
+                                Type ret_s = desc_s.getReturnType();
+                                scanLambdaBody(tree, ret_t, ret_s);
+                            }
+                            return;
+                        }
+                    }
+                    result &= MostSpecificCheckContext.super.compatible(t, s, warn);
+                }
+                //where
+
+                void scanLambdaBody(JCLambda lambda, final Type t, final Type s) {
+                    if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
+                        result &= MostSpecificCheckContext.this.mostSpecific(t, s, lambda.body, warn);
+                    } else {
+                        DeferredAttr.LambdaReturnScanner lambdaScanner =
+                                new DeferredAttr.LambdaReturnScanner() {
+                                    @Override
+                                    public void visitReturn(JCReturn tree) {
+                                        if (tree.expr != null) {
+                                            result &= MostSpecificCheckContext.this.mostSpecific(t, s, tree.expr, warn);
+                                        }
+                                    }
+                                };
+                        lambdaScanner.scan(lambda.body);
+                    }
+                }
+            }
         }
     }
 
@@ -1071,7 +1243,7 @@
         Assert.check(sym.kind < AMBIGUOUS);
         try {
             Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes,
-                               allowBoxing, useVarargs, types.noWarnings);
+                               allowBoxing, useVarargs, types.noWarnings, resolveMethodCheck);
             if (!operator)
                 currentResolutionContext.addApplicableCandidate(sym, mt);
         } catch (InapplicableMethodException ex) {
@@ -1151,198 +1323,50 @@
                 if (m1Abstract && !m2Abstract) return m2;
                 if (m2Abstract && !m1Abstract) return m1;
                 // both abstract or both concrete
-                if (!m1Abstract && !m2Abstract)
-                    return ambiguityError(m1, m2);
-                // check that both signatures have the same erasure
-                if (!types.isSameTypes(m1.erasure(types).getParameterTypes(),
-                                       m2.erasure(types).getParameterTypes()))
-                    return ambiguityError(m1, m2);
-                // both abstract, neither overridden; merge throws clause and result type
-                Type mst = mostSpecificReturnType(mt1, mt2);
-                if (mst == null) {
-                    // Theoretically, this can't happen, but it is possible
-                    // due to error recovery or mixing incompatible class files
-                    return ambiguityError(m1, m2);
-                }
-                Symbol mostSpecific = mst == mt1 ? m1 : m2;
-                List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
-                Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
-                MethodSymbol result = new MethodSymbol(
-                        mostSpecific.flags(),
-                        mostSpecific.name,
-                        newSig,
-                        mostSpecific.owner) {
-                    @Override
-                    public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
-                        if (origin == site.tsym)
-                            return this;
-                        else
-                            return super.implementation(origin, types, checkResult);
-                        }
-                    };
-                return result;
+                return ambiguityError(m1, m2);
             }
             if (m1SignatureMoreSpecific) return m1;
             if (m2SignatureMoreSpecific) return m2;
             return ambiguityError(m1, m2);
         case AMBIGUOUS:
+            //check if m1 is more specific than all ambiguous methods in m2
             AmbiguityError e = (AmbiguityError)m2;
-            Symbol err1 = mostSpecific(argtypes, m1, e.sym, env, site, allowBoxing, useVarargs);
-            Symbol err2 = mostSpecific(argtypes, m1, e.sym2, env, site, allowBoxing, useVarargs);
-            if (err1 == err2) return err1;
-            if (err1 == e.sym && err2 == e.sym2) return m2;
-            if (err1 instanceof AmbiguityError &&
-                err2 instanceof AmbiguityError &&
-                ((AmbiguityError)err1).sym == ((AmbiguityError)err2).sym)
-                return ambiguityError(m1, m2);
-            else
-                return ambiguityError(err1, err2);
+            for (Symbol s : e.ambiguousSyms) {
+                if (mostSpecific(argtypes, m1, s, env, site, allowBoxing, useVarargs) != m1) {
+                    return e.append(m1);
+                }
+            }
+            return m1;
         default:
             throw new AssertionError();
         }
     }
     //where
     private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
-        Symbol m12 = adjustVarargs(m1, m2, useVarargs);
-        Symbol m22 = adjustVarargs(m2, m1, useVarargs);
-        Type mtype1 = types.memberType(site, m12);
-        Type mtype2 = types.memberType(site, m22);
-
-        //check if invocation is more specific
-        if (invocationMoreSpecific(env, site, m22, mtype1.getParameterTypes(), allowBoxing, useVarargs)) {
-            return true;
-        }
-
-        //perform structural check
-
-        List<Type> formals1 = mtype1.getParameterTypes();
-        Type lastFormal1 = formals1.last();
-        List<Type> formals2 = mtype2.getParameterTypes();
-        Type lastFormal2 = formals2.last();
-        ListBuffer<Type> newFormals = ListBuffer.lb();
-
-        boolean hasStructuralPoly = false;
-        for (Type actual : actuals) {
-            //perform formal argument adaptation in case actuals > formals (varargs)
-            Type f1 = formals1.isEmpty() ?
-                    lastFormal1 : formals1.head;
-            Type f2 = formals2.isEmpty() ?
-                    lastFormal2 : formals2.head;
-
-            //is this a structural actual argument?
-            boolean isStructuralPoly = actual.hasTag(DEFERRED) &&
-                    (((DeferredType)actual).tree.hasTag(LAMBDA) ||
-                    ((DeferredType)actual).tree.hasTag(REFERENCE));
-
-            Type newFormal = f1;
-
-            if (isStructuralPoly) {
-                //for structural arguments only - check that corresponding formals
-                //are related - if so replace formal with <null>
-                hasStructuralPoly = true;
-                DeferredType dt = (DeferredType)actual;
-                Type t1 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m1, currentResolutionContext.step).apply(dt);
-                Type t2 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m2, currentResolutionContext.step).apply(dt);
-                if (t1.isErroneous() || t2.isErroneous() || !isStructuralSubtype(t1, t2)) {
-                    //not structural subtypes - simply fail
-                    return false;
-                } else {
-                    newFormal = syms.botType;
-                }
-            }
-
-            newFormals.append(newFormal);
-            if (newFormals.length() > mtype2.getParameterTypes().length()) {
-                //expand m2's type so as to fit the new formal arity (varargs)
-                m22.type = types.createMethodTypeWithParameters(m22.type, m22.type.getParameterTypes().append(f2));
-            }
-
-            formals1 = formals1.isEmpty() ? formals1 : formals1.tail;
-            formals2 = formals2.isEmpty() ? formals2 : formals2.tail;
-        }
-
-        if (!hasStructuralPoly) {
-            //if no structural actual was found, we're done
-            return false;
-        }
-        //perform additional adaptation if actuals < formals (varargs)
-        for (Type t : formals1) {
-            newFormals.append(t);
-        }
-        //check if invocation (with tweaked args) is more specific
-        return invocationMoreSpecific(env, site, m22, newFormals.toList(), allowBoxing, useVarargs);
-    }
-    //where
-    private boolean invocationMoreSpecific(Env<AttrContext> env, Type site, Symbol m2, List<Type> argtypes1, boolean allowBoxing, boolean useVarargs) {
         noteWarner.clear();
+        int maxLength = Math.max(
+                            Math.max(m1.type.getParameterTypes().length(), actuals.length()),
+                            m2.type.getParameterTypes().length());
         Type mst = instantiate(env, site, m2, null,
-                types.lowerBounds(argtypes1), null,
-                allowBoxing, false, noteWarner);
+                adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null,
+                allowBoxing, useVarargs, noteWarner, new MostSpecificCheck(!allowBoxing, actuals));
         return mst != null &&
                 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
     }
-    //where
-    private Symbol adjustVarargs(Symbol to, Symbol from, boolean useVarargs) {
-        List<Type> fromArgs = from.type.getParameterTypes();
-        List<Type> toArgs = to.type.getParameterTypes();
-        if (useVarargs &&
-                (from.flags() & VARARGS) != 0 &&
-                (to.flags() & VARARGS) != 0) {
-            Type varargsTypeFrom = fromArgs.last();
-            Type varargsTypeTo = toArgs.last();
-            ListBuffer<Type> args = ListBuffer.lb();
-            if (toArgs.length() < fromArgs.length()) {
-                //if we are checking a varargs method 'from' against another varargs
-                //method 'to' (where arity of 'to' < arity of 'from') then expand signature
-                //of 'to' to 'fit' arity of 'from' (this means adding fake formals to 'to'
-                //until 'to' signature has the same arity as 'from')
-                while (fromArgs.head != varargsTypeFrom) {
-                    args.append(toArgs.head == varargsTypeTo ? types.elemtype(varargsTypeTo) : toArgs.head);
-                    fromArgs = fromArgs.tail;
-                    toArgs = toArgs.head == varargsTypeTo ?
-                        toArgs :
-                        toArgs.tail;
-                }
-            } else {
-                //formal argument list is same as original list where last
-                //argument (array type) is removed
-                args.appendList(toArgs.reverse().tail.reverse());
+    private List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) {        
+        if ((msym.flags() & VARARGS) != 0 && allowVarargs) {            
+            Type varargsElem = types.elemtype(args.last());
+            Assert.check(varargsElem != null, "Bad varargs = " + args.last() + " " + msym);
+            List<Type> newArgs = args.reverse().tail.prepend(varargsElem).reverse();
+            while (newArgs.length() < length) {
+                newArgs = newArgs.append(newArgs.last());
             }
-            //append varargs element type as last synthetic formal
-            args.append(types.elemtype(varargsTypeTo));
-            Type mtype = types.createMethodTypeWithParameters(to.type, args.toList());
-            return new MethodSymbol(to.flags_field & ~VARARGS, to.name, mtype, to.owner);
+            return newArgs;
         } else {
-            return to;
+            return args;
         }
     }
     //where
-    boolean isStructuralSubtype(Type s, Type t) {
-
-        Type ret_s = types.findDescriptorType(s).getReturnType();
-        Type ret_t = types.findDescriptorType(t).getReturnType();
-
-        //covariant most specific check for function descriptor return type
-        if (!types.isSubtype(ret_s, ret_t)) {
-            return false;
-        }
-
-        List<Type> args_s = types.findDescriptorType(s).getParameterTypes();
-        List<Type> args_t = types.findDescriptorType(t).getParameterTypes();
-
-        //arity must be identical
-        if (args_s.length() != args_t.length()) {
-            return false;
-        }
-
-        //invariant most specific check for function descriptor parameter types
-        if (!types.isSameTypes(args_t, args_s)) {
-            return false;
-        }
-
-        return true;
-    }
-    //where
     Type mostSpecificReturnType(Type mt1, Type mt2) {
         Type rt1 = mt1.getReturnType();
         Type rt2 = mt2.getReturnType();
@@ -2355,9 +2379,11 @@
         try {
             currentResolutionContext = new MethodResolutionContext();
             Name name = treeinfo.operatorName(optag);
+            env.info.pendingResolutionPhase = currentResolutionContext.step = BASIC;
             Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
                                     null, false, false, true);
             if (boxingEnabled && sym.kind >= WRONG_MTHS)
+                env.info.pendingResolutionPhase = currentResolutionContext.step = BOX;
                 sym = findMethod(env, syms.predefClass.type, name, argtypes,
                                  null, true, false, true);
             return accessMethod(sym, pos, env.enclClass.sym.type, name,
@@ -2513,11 +2539,15 @@
 
         @Override
         Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+            if (sym.kind == AMBIGUOUS) {
+                AmbiguityError a_err = (AmbiguityError)sym;
+                sym = a_err.mergeAbstracts(site);
+            }
             if (sym.kind >= AMBIGUOUS) {
                 //if nothing is found return the 'first' error
                 sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes);
             }
-            return sym;
+            return sym;            
         }
     }
 
@@ -2568,6 +2598,10 @@
         abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
 
         Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+            if (sym.kind == AMBIGUOUS) {
+                AmbiguityError a_err = (AmbiguityError)sym;
+                sym = a_err.mergeAbstracts(site);
+            }
             //skip error reporting
             return sym;
         }
@@ -3327,14 +3361,33 @@
      * (either methods, constructors or operands) are ambiguous
      * given an actual arguments/type argument list.
      */
-    class AmbiguityError extends InvalidSymbolError {
+    class AmbiguityError extends ResolveError {
 
         /** The other maximally specific symbol */
-        Symbol sym2;
-
+        Set<Symbol> ambiguousSyms = new LinkedHashSet<Symbol>();
+
+        @Override
+        public boolean exists() {
+            return true;
+        }
+        
         AmbiguityError(Symbol sym1, Symbol sym2) {
-            super(AMBIGUOUS, sym1, "ambiguity error");
-            this.sym2 = sym2;
+            super(AMBIGUOUS, "ambiguity error");
+            this.ambiguousSyms.addAll(flatten(sym1));
+            this.ambiguousSyms.addAll(flatten(sym2));
+        }
+        
+        private Collection<Symbol> flatten(Symbol sym) {
+            if (sym.kind == AMBIGUOUS) {
+                return ((AmbiguityError)sym).ambiguousSyms;
+            } else {
+                return List.of(sym);
+            }
+        }
+
+        AmbiguityError append(Symbol s) {
+            ambiguousSyms.add(s);
+            return this;
         }
 
         @Override
@@ -3345,24 +3398,59 @@
                 Name name,
                 List<Type> argtypes,
                 List<Type> typeargtypes) {
-            AmbiguityError pair = this;
-            while (true) {
-                if (pair.sym.kind == AMBIGUOUS)
-                    pair = (AmbiguityError)pair.sym;
-                else if (pair.sym2.kind == AMBIGUOUS)
-                    pair = (AmbiguityError)pair.sym2;
-                else break;
+            Symbol[] diagSyms = new Symbol[2];
+            //keep track of first two symbols (needed for diagnostic compatibility)
+            int i = 0;
+            for (Symbol s : ambiguousSyms) {
+                if (i >= diagSyms.length) break;
+                diagSyms[i++] = s;                
             }
-            Name sname = pair.sym.name;
-            if (sname == names.init) sname = pair.sym.owner.name;
+            Name sname = diagSyms[0].name;
+            if (sname == names.init) sname = diagSyms[0].owner.name;
             return diags.create(dkind, log.currentSource(),
                       pos, "ref.ambiguous", sname,
-                      kindName(pair.sym),
-                      pair.sym,
-                      pair.sym.location(site, types),
-                      kindName(pair.sym2),
-                      pair.sym2,
-                      pair.sym2.location(site, types));
+                      kindName(diagSyms[0]),
+                      diagSyms[0],
+                      diagSyms[0].location(site, types),
+                      kindName(diagSyms[1]),
+                      diagSyms[1],
+                      diagSyms[1].location(site, types));
+        }
+        
+        /**
+         * If multiple applicable methods are found during overload and none of them
+         * is more specific than the others, attempt to merge their signatures.
+         */
+        Symbol mergeAbstracts(Type site) {
+            Symbol fst = ambiguousSyms.iterator().next();
+            Symbol res = fst;
+            for (Symbol s : ambiguousSyms) {
+                Type mt1 = types.memberType(site, res);
+                Type mt2 = types.memberType(site, s);
+                if ((s.flags() & ABSTRACT) == 0 ||
+                        !types.overrideEquivalent(mt1, mt2) ||
+                        !types.isSameTypes(fst.erasure(types).getParameterTypes(),
+                                       s.erasure(types).getParameterTypes())) {
+                    //ambiguity cannot be resolved
+                    return this;
+                } else {                    
+                    Type mst = mostSpecificReturnType(mt1, mt2);
+                    if (mst == null) {
+                        // Theoretically, this can't happen, but it is possible
+                        // due to error recovery or mixing incompatible class files
+                        return this;
+                    }
+                    Symbol mostSpecific = mst == mt1 ? res : s;
+                    List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
+                    Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
+                    res = new MethodSymbol(
+                            mostSpecific.flags(),
+                            mostSpecific.name,
+                            newSig,
+                            mostSpecific.owner);
+                }
+            }
+            return res;
         }
     }
 
@@ -3438,6 +3526,10 @@
             Candidate c = new Candidate(currentResolutionContext.step, sym, null, mtype);
             candidates = candidates.append(c);
         }
+        
+        DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext) {
+            return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext);
+        }
 
         /**
          * This class represents an overload resolution candidate. There are two
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Dec 17 15:36:20 2012 +0000
@@ -39,7 +39,6 @@
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Scope.*;
 import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.comp.Attr.FunctionalInfo;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
@@ -377,6 +376,11 @@
             return (this.ordinal() - POS.ordinal());
         }
     }
+    
+    public enum PolyKind {
+        STANDALONE,
+        POLY;
+    }
 
     /* The (encoded) position in the source file. @see util.Position.
      */
@@ -604,6 +608,16 @@
             return this;
         }
     }
+    
+    /**
+     * Common supertype for all functional expression trees (lambda and method references)
+     */
+    public static abstract class JCFunctionalExpression extends JCExpression {
+        /** target descriptor inferred for this functional expression. */
+        public Type descriptorType;
+        /** list of target types inferred for this functional expression. */
+        public List<Symbol> targets;
+    }
 
     /**
      * A class definition.
@@ -1154,6 +1168,7 @@
         public JCExpression cond;
         public JCExpression truepart;
         public JCExpression falsepart;
+        public PolyKind polyKind;
         protected JCConditional(JCExpression cond,
                               JCExpression truepart,
                               JCExpression falsepart)
@@ -1381,6 +1396,7 @@
         public JCExpression meth;
         public List<JCExpression> args;
         public Type varargsElement;
+        public PolyKind polyKind;
         protected JCMethodInvocation(List<JCExpression> typeargs,
                         JCExpression meth,
                         List<JCExpression> args)
@@ -1428,6 +1444,7 @@
         public Symbol constructor;
         public Type varargsElement;
         public Type constructorType;
+        public PolyKind polyKind;
         protected JCNewClass(JCExpression encl,
                            List<JCExpression> typeargs,
                            JCExpression clazz,
@@ -1505,18 +1522,29 @@
     /**
      * A lambda expression.
      */
-    public static class JCLambda extends JCExpression implements LambdaExpressionTree {
+    public static class JCLambda extends JCFunctionalExpression implements LambdaExpressionTree {
+        
+        public enum ParameterKind {
+            IMPLICIT,
+            EXPLICIT;
+        }
 
         public List<JCVariableDecl> params;
         public JCTree body;
-        public FunctionalInfo fInfo;
         public boolean canCompleteNormally = true;
         public List<Type> inferredThrownTypes;
+        public ParameterKind paramKind;
 
         public JCLambda(List<JCVariableDecl> params,
                         JCTree body) {
             this.params = params;
             this.body = body;
+            if (params.isEmpty() ||
+                params.head.vartype != null) {
+                paramKind = ParameterKind.EXPLICIT;
+            } else {
+                paramKind = ParameterKind.IMPLICIT;
+            }
         }
         @Override
         public Tag getTag() {
@@ -1815,15 +1843,15 @@
     /**
      * Selects a member expression.
      */
-    public static class JCMemberReference extends JCExpression implements MemberReferenceTree {
+    public static class JCMemberReference extends JCFunctionalExpression implements MemberReferenceTree {
         public ReferenceMode mode;
         public ReferenceKind kind;
         public Name name;
         public JCExpression expr;
         public List<JCExpression> typeargs;
-        public FunctionalInfo fInfo;
         public Symbol sym;
         public Type varargsElement;
+        public PolyKind polyKind;
 
         /**
          * Javac-dependent classification for member references, based
--- a/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon Dec 17 15:36:20 2012 +0000
@@ -945,7 +945,7 @@
     public void visitLambda(JCLambda tree) {
         try {
             print("(");
-            if (TreeInfo.isExplicitLambda(tree)) {
+            if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT) {
                 printExprs(tree.params);
             } else {
                 String sep = "";
--- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Dec 17 15:36:20 2012 +0000
@@ -262,10 +262,39 @@
                 return false;
         }
     }
-
-    public static boolean isExplicitLambda(JCLambda lambda) {
-        return lambda.params.isEmpty() ||
-                lambda.params.head.vartype != null;
+    
+    /** set 'polyKind' on given tree */
+    public static void setPolyKind(JCTree tree, PolyKind pkind) {
+        switch (tree.getTag()) {
+            case APPLY:
+                ((JCMethodInvocation)tree).polyKind = pkind;
+                break;
+            case NEWCLASS:
+                ((JCNewClass)tree).polyKind = pkind;
+                break;
+            case REFERENCE:
+                ((JCMemberReference)tree).polyKind = pkind;
+                break;
+            default:
+                throw new AssertionError(String.format("Unexpected tree %s", tree));
+        }
+    }
+    
+    /** set 'varargsElement' on given tree */
+    public static void setVarargsElement(JCTree tree, Type varargsElement) {
+        switch (tree.getTag()) {
+            case APPLY:
+                ((JCMethodInvocation)tree).varargsElement = varargsElement;
+                break;
+            case NEWCLASS:
+                ((JCNewClass)tree).varargsElement = varargsElement;
+                break;
+            case REFERENCE:
+                ((JCMemberReference)tree).varargsElement = varargsElement;
+                break;
+            default:
+                throw new AssertionError(String.format("Unexpected tree %s", tree));
+        }
     }
 
     /** Return true if the tree corresponds to an expression statement */
--- a/test/tools/javac/Diagnostics/6722234/T6722234d_1.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/Diagnostics/6722234/T6722234d_1.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,3 +1,3 @@
-T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.intersection.type: 1, T6722234d.A)
+T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: compiler.misc.intersection.type: 1, T6722234d.A,java.lang.Object)
 - compiler.misc.where.description.intersection: compiler.misc.intersection.type: 1,{(compiler.misc.where.intersection: compiler.misc.intersection.type: 1, java.lang.Object,T6722234d.I1,T6722234d.I2)}
 1 error
--- a/test/tools/javac/Diagnostics/6722234/T6722234d_2.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/Diagnostics/6722234/T6722234d_2.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,3 +1,3 @@
-T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.intersection.type: 1, T6722234d.A)
+T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: compiler.misc.intersection.type: 1, T6722234d.A,Object)
 - compiler.misc.where.description.intersection: compiler.misc.intersection.type: 1,{(compiler.misc.where.intersection: compiler.misc.intersection.type: 1, Object,I1,I2)}
 1 error
--- a/test/tools/javac/diags/examples.not-yet.txt	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/diags/examples.not-yet.txt	Mon Dec 17 15:36:20 2012 +0000
@@ -58,6 +58,7 @@
 compiler.misc.fatal.err.cant.close	                # JavaCompiler
 compiler.misc.file.does.not.contain.package
 compiler.misc.illegal.start.of.class.file
+compiler.misc.inferred.do.not.conform.to.lower.bounds   # cannot happen?
 compiler.misc.kindname.annotation
 compiler.misc.kindname.enum
 compiler.misc.kindname.package
@@ -67,6 +68,7 @@
 compiler.misc.kindname.value
 compiler.misc.incompatible.eq.lower.bounds              # cannot happen?
 compiler.misc.no.unique.minimal.instance.exists
+compiler.misc.no.unique.maximal.instance.exists         # cannot happen?
 compiler.misc.resume.abort                              # prompt for a response
 compiler.misc.source.unavailable                        # DiagnosticSource
 compiler.misc.token.bad-symbol
--- a/test/tools/javac/diags/examples/CyclicInference.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/diags/examples/CyclicInference.java	Mon Dec 17 15:36:20 2012 +0000
@@ -21,7 +21,7 @@
  * questions.
  */
 
-// key: compiler.err.cant.apply.symbol
+// key: compiler.err.prob.found.req
 // key: compiler.misc.cyclic.inference
 
 class CyclicInference {
--- a/test/tools/javac/diags/examples/InferredDoNotConformToLower.java	Mon Dec 17 01:59:19 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +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.inferred.do.not.conform.to.lower.bounds
-
-import java.util.*;
-
-class InferredDoNotConformToLower {
-    <X extends Number> List<X> m() { return null; }
-    { List<? super String> lss = this.m(); }
-}
--- a/test/tools/javac/diags/examples/NoUniqueMaximalInstance.java	Mon Dec 17 01:59:19 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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.no.unique.maximal.instance.exists
-
-class NoUniqueMaximalInstance {
-    <Z extends Integer> Z m() { return null; }
-
-    { String s = m(); }
-}
--- a/test/tools/javac/diags/examples/WhereIntersection.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/diags/examples/WhereIntersection.java	Mon Dec 17 15:36:20 2012 +0000
@@ -25,7 +25,7 @@
 // key: compiler.misc.where.description.intersection
 // key: compiler.misc.intersection.type
 // key: compiler.err.prob.found.req
-// key: compiler.misc.inconvertible.types
+// key: compiler.misc.inferred.do.not.conform.to.upper.bounds
 // options: -XDdiags=where
 // run: simple
 
--- a/test/tools/javac/failover/CheckAttributedTree.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/failover/CheckAttributedTree.java	Mon Dec 17 15:36:20 2012 +0000
@@ -376,7 +376,7 @@
                     that.hasTag(CLASSDEF);
         }
 
-        private final List<String> excludedFields = Arrays.asList("varargsElement", "targetType");
+        private final List<String> excludedFields = Arrays.asList("varargsElement");
 
         void check(boolean ok, String label, Info self) {
             if (!ok) {
--- a/test/tools/javac/generics/diamond/T6939780.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/generics/diamond/T6939780.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,3 +1,4 @@
+T6939780.java:18:33: compiler.warn.diamond.redundant.args: Foo<java.lang.Number>, Foo<java.lang.Number>
 T6939780.java:19:28: compiler.warn.diamond.redundant.args: Foo<java.lang.Number>, Foo<java.lang.Number>
 T6939780.java:20:28: compiler.warn.diamond.redundant.args.1: Foo<java.lang.Integer>, Foo<java.lang.Number>
-2 warnings
+3 warnings
--- a/test/tools/javac/generics/diamond/neg/Neg05.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/generics/diamond/neg/Neg05.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,25 +1,25 @@
 Neg05.java:19:48: compiler.err.improperly.formed.type.inner.raw.param
-Neg05.java:19:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo<java.lang.String>, Neg05<?>.Foo<java.lang.String>)
 Neg05.java:20:58: compiler.err.improperly.formed.type.inner.raw.param
-Neg05.java:20:45: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo<java.lang.String>, Neg05<?>.Foo<? extends java.lang.String>)
 Neg05.java:21:43: compiler.err.improperly.formed.type.inner.raw.param
-Neg05.java:21:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo<java.lang.String>, Neg05<?>.Foo<?>)
 Neg05.java:22:56: compiler.err.improperly.formed.type.inner.raw.param
-Neg05.java:22:43: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo<java.lang.String>, Neg05<?>.Foo<? super java.lang.String>)
 Neg05.java:24:48: compiler.err.improperly.formed.type.inner.raw.param
-Neg05.java:24:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo<java.lang.String>, Neg05<?>.Foo<java.lang.String>)
 Neg05.java:25:58: compiler.err.improperly.formed.type.inner.raw.param
-Neg05.java:25:45: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo<java.lang.String>, Neg05<?>.Foo<? extends java.lang.String>)
 Neg05.java:26:43: compiler.err.improperly.formed.type.inner.raw.param
-Neg05.java:26:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo<java.lang.String>, Neg05<?>.Foo<?>)
 Neg05.java:27:56: compiler.err.improperly.formed.type.inner.raw.param
-Neg05.java:27:43: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo<java.lang.String>, Neg05<?>.Foo<? super java.lang.String>)
 Neg05.java:31:37: compiler.err.improperly.formed.type.inner.raw.param
+Neg05.java:31:44: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V, Neg05.Foo<V>, Neg05<?>.Foo<java.lang.String>))
 Neg05.java:32:47: compiler.err.improperly.formed.type.inner.raw.param
+Neg05.java:32:54: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V, Neg05.Foo<V>, Neg05<?>.Foo<? extends java.lang.String>))
 Neg05.java:33:32: compiler.err.improperly.formed.type.inner.raw.param
+Neg05.java:33:39: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V, Neg05.Foo<V>, Neg05<?>.Foo<?>))
 Neg05.java:34:45: compiler.err.improperly.formed.type.inner.raw.param
+Neg05.java:34:52: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V, Neg05.Foo<V>, Neg05<?>.Foo<? super java.lang.String>))
 Neg05.java:36:37: compiler.err.improperly.formed.type.inner.raw.param
+Neg05.java:36:44: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V,Z, Neg05.Foo<V>, Neg05<?>.Foo<java.lang.String>))
 Neg05.java:37:47: compiler.err.improperly.formed.type.inner.raw.param
+Neg05.java:37:54: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V,Z, Neg05.Foo<V>, Neg05<?>.Foo<? extends java.lang.String>))
 Neg05.java:38:32: compiler.err.improperly.formed.type.inner.raw.param
+Neg05.java:38:39: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V,Z, Neg05.Foo<V>, Neg05<?>.Foo<?>))
 Neg05.java:39:45: compiler.err.improperly.formed.type.inner.raw.param
+Neg05.java:39:52: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V,Z, Neg05.Foo<V>, Neg05<?>.Foo<? super java.lang.String>))
 24 errors
--- a/test/tools/javac/generics/diamond/neg/Neg10.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/generics/diamond/neg/Neg10.java	Mon Dec 17 15:36:20 2012 +0000
@@ -4,8 +4,8 @@
  *
  * @summary  Check that 'complex' diamond can infer type that is too specific
  * @author mcimadamore
- * @compile/fail/ref=Neg10.out Neg10.java -XDrawDiagnostics
- * @compile Neg10.java -XDuseGraphInference -XDrawDiagnostics
+ * @compile/fail/ref=Neg10.out -source 7 -Xlint:-options Neg10.java -XDrawDiagnostics
+ * @compile Neg10.java -XDrawDiagnostics
  *
  */
 
--- a/test/tools/javac/generics/inference/6315770/T6315770.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/generics/inference/6315770/T6315770.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,3 +1,3 @@
-T6315770.java:16:42: compiler.err.prob.found.req: (compiler.misc.no.unique.maximal.instance.exists: T, java.lang.String,java.lang.Integer,java.lang.Runnable)
-T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.Integer&java.lang.Runnable, java.lang.String)
+T6315770.java:16:42: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: T, java.lang.String,java.lang.Integer,java.lang.Runnable)
+T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Integer,java.lang.Runnable)
 2 errors
--- a/test/tools/javac/generics/inference/6638712/T6638712b.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/generics/inference/6638712/T6638712b.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,2 +1,2 @@
-T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, java.lang.String,java.lang.Object)
+T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: T, java.lang.Integer, java.lang.String,java.lang.Object)
 1 error
--- a/test/tools/javac/generics/inference/6650759/T6650759m.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/generics/inference/6650759/T6650759m.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,2 +1,2 @@
-T6650759m.java:43:36: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.Integer, java.lang.String)
+T6650759m.java:43:36: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Integer,java.lang.Object)
 1 error
--- a/test/tools/javac/lambda/MethodReference25.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/MethodReference25.java	Mon Dec 17 15:36:20 2012 +0000
@@ -25,21 +25,13 @@
  * @test
  * @bug 8003280
  * @summary Add lambda tests
- *  check that non-boxing method references conversion has the precedence
- * @run main MethodReference25
+ *  check that non-boxing method references is not preferred over boxing one
+ * @compile/fail/ref=MethodReference25.out -XDrawDiagnostics MethodReference25.java
  */
 
-public class MethodReference25 {
+class MethodReference25 {
 
-    static void assertTrue(boolean cond) {
-        assertionCount++;
-        if (!cond)
-            throw new AssertionError();
-    }
-
-    static int assertionCount = 0;
-
-    static void m(Integer i) { assertTrue(true); }
+    static void m(Integer i) { }
 
     interface SAM1 {
         void m(int x);
@@ -49,11 +41,10 @@
         void m(Integer x);
     }
 
-    static void call(int i, SAM1 s) { s.m(i); assertTrue(false); }
+    static void call(int i, SAM1 s) { s.m(i);  }
     static void call(int i, SAM2 s) { s.m(i);  }
 
     public static void main(String[] args) {
-        call(1, MethodReference25::m); //resolves to call(int, SAM2)
-        assertTrue(assertionCount == 1);
+        call(1, MethodReference25::m); //ambiguous
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference25.out	Mon Dec 17 15:36:20 2012 +0000
@@ -0,0 +1,2 @@
+MethodReference25.java:48:9: compiler.err.ref.ambiguous: call, kindname.method, call(int,MethodReference25.SAM1), MethodReference25, kindname.method, call(int,MethodReference25.SAM2), MethodReference25
+1 error
--- a/test/tools/javac/lambda/MethodReference26.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/MethodReference26.java	Mon Dec 17 15:36:20 2012 +0000
@@ -1,9 +1,30 @@
 /*
- * @test /nodynamiccopyright/
- * @bug 8003280
- * @summary Add lambda tests
- *  check strict method conversion does not allow loose method reference conversion
- * @compile/fail/ref=MethodReference26.out -XDrawDiagnostics MethodReference26.java
+ * Copyright (c) 2011, 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
+ * @summary check strict method conversion allows loose method reference conversion
+ * @compile MethodReference26.java
  */
 
 class MethodReference26 {
@@ -18,6 +39,6 @@
     static void call(Integer i, SAM s) {   }
 
     static void test() {
-        call(1, MethodReference26::m); //ambiguous
+        call(1, MethodReference26::m); //ok
     }
 }
--- a/test/tools/javac/lambda/MethodReference26.out	Mon Dec 17 01:59:19 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-MethodReference26.java:21:9: compiler.err.ref.ambiguous: call, kindname.method, call(int,MethodReference26.SAM), MethodReference26, kindname.method, call(java.lang.Integer,MethodReference26.SAM), MethodReference26
-1 error
--- a/test/tools/javac/lambda/MethodReference43.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/MethodReference43.java	Mon Dec 17 15:36:20 2012 +0000
@@ -60,9 +60,9 @@
 
 
     static void m(SAM1 s) { assertTrue(false); }
-    static void m(SAM2 s) { assertTrue(true); }
+    static void m(SAM2 s) { assertTrue(false); }
     static void m(SAM3 s) { assertTrue(false); }
-    static void m(SAM4 s) { assertTrue(false); }
+    static void m(SAM4 s) { assertTrue(true); }
 
     public static void main(String[] args) {
         m(Foo::new);
--- a/test/tools/javac/lambda/TargetType01.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType01.java	Mon Dec 17 15:36:20 2012 +0000
@@ -27,7 +27,7 @@
  * @summary Add lambda tests
  *  check nested case of overload resolution and lambda parameter inference
  * @author  Maurizio Cimadamore
- * @compile TargetType01.java
+ * @compile/fail/ref=TargetType01.out -XDrawDiagnostics TargetType01.java
  */
 
 class TargetType01 {
@@ -42,8 +42,7 @@
     static Integer M(F_I_I f){ return null; }
     static String M(F_S_S f){ return null; }
 
-    static {
-        //ambiguity here - the compiler does not try all the combinations!
-        M(x1 -> { return M( x2 -> { return x1 + x2; });});
+    static {        
+        M(x1 -> { return M( x2 -> { return x1 + x2; });}); //ambiguous
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType01.out	Mon Dec 17 15:36:20 2012 +0000
@@ -0,0 +1,3 @@
+TargetType01.java:46:9: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01
+TargetType01.java:46:26: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01
+2 errors
--- a/test/tools/javac/lambda/TargetType06.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType06.java	Mon Dec 17 15:36:20 2012 +0000
@@ -4,7 +4,7 @@
  * @summary Add lambda tests
  *  check complex case of target typing
  * @author  Maurizio Cimadamore
- * @compile/fail/ref=TargetType06.out -XDrawDiagnostics TargetType06.java
+ * @compile TargetType06.java
  */
 
 import java.util.List;
--- a/test/tools/javac/lambda/TargetType10.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType10.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,2 +1,2 @@
-TargetType10.java:18:11: compiler.err.cant.apply.symbol: kindname.method, compose, TargetType10.Function<B,C>,TargetType10.Function<A,? extends B>, @569,@584, kindname.class, TargetType10.Test, (compiler.misc.cyclic.inference: B,A)
+TargetType10.java:18:18: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: B,A)
 1 error
--- a/test/tools/javac/lambda/TargetType11.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType11.java	Mon Dec 17 15:36:20 2012 +0000
@@ -4,7 +4,7 @@
  * @summary Add lambda tests
  *  check that wildcards in the target method of a lambda conversion is handled correctly
  * @author  Maurizio Cimadamore
- * @compile/fail/ref=TargetType11.out -Xlint:unchecked -XDrawDiagnostics TargetType11.java
+ * @compile TargetType11.java
  */
 
 class TargetType11 {
--- a/test/tools/javac/lambda/TargetType14.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType14.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,2 +1,2 @@
-TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TargetType14.SAM<java.lang.String>, TargetType14.SAM<java.lang.Integer>)
+TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.Integer, java.lang.String)
 1 error
--- a/test/tools/javac/lambda/TargetType21.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType21.java	Mon Dec 17 15:36:20 2012 +0000
@@ -25,9 +25,9 @@
     <R,A> void call(SAM3<R,A> sam) { }
 
     void test() {
-        call(x -> { throw new Exception(); }); //ok - resolves to call(SAM1)
-        call(x -> { System.out.println(""); }); //ok - resolves to call(SAM2)
-        call(x -> { return (Object) null; }); //error - call(SAM3) is not applicable because of cyclic inference
-        call(x -> { return null; }); ////ok - resolves to call(SAM1)
+        call(x -> { throw new Exception(); }); //ambiguous
+        call(x -> { System.out.println(""); }); //ambiguous
+        call(x -> { return (Object) null; }); //cyclic inference
+        call(x -> { return null; }); //ambiguous
     }
 }
--- a/test/tools/javac/lambda/TargetType21.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType21.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,3 +1,6 @@
-TargetType21.java:28:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, call(TargetType21.SAM2), TargetType21
-TargetType21.java:30:9: compiler.err.cant.apply.symbols: kindname.method, call, @755,{(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, <R,A>call(TargetType21.SAM3<R,A>), (compiler.misc.cyclic.inference: A))}
-2 errors
+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
--- a/test/tools/javac/lambda/TargetType26.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType26.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,2 +1,2 @@
-TargetType26.java:16:7: compiler.err.cant.apply.symbol: kindname.method, call, Z, @340, kindname.class, TargetType26, (compiler.misc.cyclic.inference: Z)
+TargetType26.java:16:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z)
 1 error
--- a/test/tools/javac/lambda/TargetType27.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType27.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,2 +1,2 @@
-TargetType27.java:18:9: compiler.err.cant.apply.symbol: kindname.method, m, TargetType27.F<A,R>, @490, kindname.class, TargetType27, (compiler.misc.cyclic.inference: R)
+TargetType27.java:18:10: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: R)
 1 error
--- a/test/tools/javac/lambda/TargetType28.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType28.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,3 +1,3 @@
-TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TargetType28.SuperFoo<java.lang.Number>, TargetType28.SuperFoo<java.lang.String>)
-TargetType28.java:21:33: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TargetType28.SuperFoo<java.lang.Number>, TargetType28.SuperFoo<java.lang.Integer>)
+TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Number, java.lang.Number,java.lang.String)
+TargetType28.java:21:33: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Number, java.lang.Number,java.lang.Integer)
 2 errors
--- a/test/tools/javac/lambda/TargetType39.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType39.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,3 +1,3 @@
-TargetType39.java:19:9: compiler.err.cant.apply.symbol: kindname.method, call, TargetType39.SAM<U,V>, @442, kindname.class, TargetType39, (compiler.misc.cyclic.inference: U)
-TargetType39.java:20:9: compiler.err.cant.apply.symbol: kindname.method, call, TargetType39.SAM<U,V>, @479, kindname.class, TargetType39, (compiler.misc.cyclic.inference: V)
+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)
 2 errors
--- a/test/tools/javac/lambda/TargetType45.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType45.java	Mon Dec 17 15:36:20 2012 +0000
@@ -3,7 +3,7 @@
  * @bug 8003280
  * @summary Add lambda tests
  *  compiler crashes during flow analysis as it fails to report diagnostics during attribution
- * @compile/fail/ref=TargetType45.out -XDrawDiagnostics TargetType45.java
+ * @compile TargetType45.java
  */
 class TargetType45 {
 
--- a/test/tools/javac/lambda/TargetType45.out	Mon Dec 17 01:59:19 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-TargetType45.java:27:28: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: U,V, (compiler.misc.inconvertible.types: TargetType45.Mapper<java.lang.String,java.lang.Integer>, TargetType45.Mapper<? super java.lang.Object,? extends java.lang.Integer>))
-1 error
--- a/test/tools/javac/lambda/TargetType50.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/TargetType50.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,3 +1,3 @@
-TargetType50.java:25:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.String, java.lang.String,java.lang.Object)
-TargetType50.java:26:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.String, java.lang.String,java.lang.Object)
+TargetType50.java:25:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: TargetType50.Sink<java.lang.Object>, TargetType50.Sink<java.lang.String>)
+TargetType50.java:26:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: TargetType50.Sink<java.lang.Object>, TargetType50.Sink<java.lang.String>)
 2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType51.java	Mon Dec 17 15:36:20 2012 +0000
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @summary smoke test for combinator-like stuck analysis
+ * @author  Maurizio Cimadamore
+ * @compile TargetType51.java
+ */
+
+import java.util.Comparator;
+
+class TargetType51 {
+
+    interface SimpleMapper<T, U> {
+       T map(U t);
+    }
+
+    interface SimpleList<X> {
+        SimpleList<X> sort(Comparator<? super X> c);
+    }
+
+    static class Person {
+        String getName() { return ""; }
+    }
+
+    <T, U extends Comparable<? super U>> Comparator<T> comparing(SimpleMapper<U, T> mapper) {  return null; }
+
+    static class F<U extends Comparable<? super U>, T> {
+        F(SimpleMapper<U, T> f) { }
+    }
+
+    void testAssignmentContext(SimpleList<Person> list, boolean cond) {
+        SimpleList<Person> p1 = list.sort(comparing(Person::getName));
+        SimpleList<Person> p2 = list.sort(comparing(x->x.getName()));
+        SimpleList<Person> p3 = list.sort(cond ? comparing(Person::getName) : comparing(x->x.getName()));
+        SimpleList<Person> p4 = list.sort((cond ? comparing(Person::getName) : comparing(x->x.getName())));
+    }
+
+    void testMethodContext(SimpleList<Person> list, boolean cond) {
+        testMethodContext(list.sort(comparing(Person::getName)), true);
+        testMethodContext(list.sort(comparing(x->x.getName())), true);
+        testMethodContext(list.sort(cond ? comparing(Person::getName) : comparing(x->x.getName())), true);
+        testMethodContext(list.sort((cond ? comparing(Person::getName) : comparing(x->x.getName()))), true);
+    }
+}
--- a/test/tools/javac/lambda/VoidCompatibility.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/VoidCompatibility.java	Mon Dec 17 15:36:20 2012 +0000
@@ -3,7 +3,7 @@
  * @bug 8003280
  * @summary Add lambda tests
  *  check that that void compatibility affects overloading as expected
- * @compile/fail/ref=VoidCompatibility.out -XDrawDiagnostics VoidCompatibility.java
+ * @compile VoidCompatibility.java
  */
 class VoidCompatibility {
 
@@ -14,13 +14,13 @@
     void schedule(Thunk<?> t) { }
 
     void test() {
-        schedule(() -> System.setProperty("done", "true")); //ambiguous
+        schedule(() -> System.setProperty("done", "true")); //non-void most specific
         schedule(() -> { System.setProperty("done", "true"); }); //1
         schedule(() -> { return System.setProperty("done", "true"); }); //2
         schedule(() -> System.out.println("done")); //1
         schedule(() -> { System.out.println("done"); }); //1
         schedule(Thread::yield); //1
-        schedule(Thread::getAllStackTraces); //ambiguous
+        schedule(Thread::getAllStackTraces); //non-void most specific
         schedule(Thread::interrupted); //1 (most specific)
     }
 }
--- a/test/tools/javac/lambda/VoidCompatibility.out	Mon Dec 17 01:59:19 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-VoidCompatibility.java:17:9: compiler.err.ref.ambiguous: schedule, kindname.method, schedule(VoidCompatibility.Runnable), VoidCompatibility, kindname.method, schedule(VoidCompatibility.Thunk<?>), VoidCompatibility
-VoidCompatibility.java:23:9: compiler.err.ref.ambiguous: schedule, kindname.method, schedule(VoidCompatibility.Runnable), VoidCompatibility, kindname.method, schedule(VoidCompatibility.Thunk<?>), VoidCompatibility
-2 errors
--- a/test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java	Mon Dec 17 15:36:20 2012 +0000
@@ -149,8 +149,7 @@
                 return false; //ambiguous target type
             }
             else if(lambdaBody == LambdaBody.IMPLICIT) {
-                if(returnValue != ReturnValue.INTEGER) //ambiguous target type
-                    return false;
+                return false;
             }
             else { //explicit parameter type
                 if(fInterface.getParameterType().equals("Integer")) //ambiguous target type
--- a/test/tools/javac/lambda/methodReference/SamConversion.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/methodReference/SamConversion.java	Mon Dec 17 15:36:20 2012 +0000
@@ -149,14 +149,6 @@
         test2(A::method3, 4);
         test2(new A()::method4, 5);
         test2(new A()::method5, 6);
-        A a = new A(A::method1); //A(Foo f) called
-        assertTrue(a.method2(1) == 11);
-        assertTrue(a.method4(1) == 11);
-        assertTrue(a.method5(1) == 11);
-        A a2 = new A(new A()::method2); //A(Bar b) called
-        assertTrue(a2.method2(1) == 12);
-        assertTrue(a2.method4(1) == 12);
-        assertTrue(a2.method5(1) == 12);
     }
 
     /**
@@ -279,7 +271,7 @@
         testConditionalExpression(false);
         testLambdaExpressionBody();
 
-        assertTrue(assertionCount == 38);
+        assertTrue(assertionCount == 32);
     }
 
     static class MyException extends Exception {}
--- a/test/tools/javac/lambda/methodReference/SamConversionComboTest.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/methodReference/SamConversionComboTest.java	Mon Dec 17 15:36:20 2012 +0000
@@ -186,10 +186,7 @@
         if(context != Context.CONSTRUCTOR && fInterface != FInterface.C && methodDef == MethodDef.METHOD6)
         //method that throws exceptions not thrown by the interface method is a mismatch
             return false;
-        if(context == Context.CONSTRUCTOR &&
-           methodReference != MethodReference.METHOD1 &&
-           methodReference != MethodReference.METHOD2 &&
-           methodReference != MethodReference.METHOD3)//ambiguous reference
+        if(context == Context.CONSTRUCTOR)
                return false;
         return true;
     }
--- a/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out	Mon Dec 17 15:36:20 2012 +0000
@@ -1,2 +1,2 @@
-InferenceTest_neg5.java:14:13: compiler.err.cant.apply.symbol: kindname.method, method1, InferenceTest_neg5.SAM1<X>, @419, kindname.class, InferenceTest_neg5, (compiler.misc.cyclic.inference: X)
+InferenceTest_neg5.java:14:21: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: X)
 1 error
--- a/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java	Mon Dec 17 01:59:19 2012 -0800
+++ b/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java	Mon Dec 17 15:36:20 2012 +0000
@@ -23,44 +23,44 @@
 
 @TraceResolve(keys={"compiler.err.ref.ambiguous"})
 class PrimitiveOverReferenceVarargsAmbiguous {
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
     static void m_byte(byte... b) {}
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS)
     static void m_byte(Byte... b) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
     static void m_short(short... s) {}
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS)
     static void m_short(Short... s) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
     static void m_int(int... i) {}
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS)
     static void m_int(Integer... i) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
     static void m_long(long... l) {}
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS)
     static void m_long(Long... l) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
     static void m_float(float... f) {}
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS)
     static void m_float(Float... f) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
     static void m_double(double... d) {}
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS)
     static void m_double(Double... d) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
     static void m_char(char... c) {}
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS)
     static void m_char(Character... c) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
     static void m_bool(boolean... z) {}
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
+    @Candidate(applicable=Phase.VARARGS)
     static void m_bool(Boolean... z) {}
 
     {