changeset 2141:eda4ff70411f

8016175: Add bottom-up type-checking support for unambiguous method references
author mcimadamore
date Fri, 28 Jun 2013 11:54:17 +0100
parents 72daa9684315
children 5b5de35cfb10
files src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java src/share/classes/com/sun/tools/javac/comp/Infer.java src/share/classes/com/sun/tools/javac/comp/Resolve.java test/tools/javac/lambda/MethodReference68.java test/tools/javac/lambda/MethodReference68.out test/tools/javac/lambda/MethodReference69.java test/tools/javac/lambda/MethodReference69.out test/tools/javac/lambda/MethodReference70.java test/tools/javac/lambda/MethodReference70.out test/tools/javac/lambda/MethodReference71.java test/tools/javac/lambda/MethodReference71.out test/tools/javac/lambda/TargetType60.out
diffstat 13 files changed, 265 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jun 06 16:04:38 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Jun 28 11:54:17 2013 +0100
@@ -2662,10 +2662,24 @@
 
             setFunctionalInfo(localEnv, that, pt(), desc, target, resultInfo.checkContext);
             List<Type> argtypes = desc.getParameterTypes();
+            
+            boolean unstickRound =
+                    resultInfo.checkContext.inferenceContext().free(argtypes);
+            
+            Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck;
+            List<Type> lookupArgs = argtypes;
+            
+            if (unstickRound) {
+                //are we in an unsticking round? If so use arity-based check and fake args
+                referenceCheck = rs.arityMethodCheck;
+                lookupArgs = rs.dummyArgs(argtypes.length());
+            }
+            
 
             Pair<Symbol, Resolve.ReferenceLookupHelper> refResult =
                     rs.resolveMemberReference(that.pos(), localEnv, that,
-                        that.expr.type, that.name, argtypes, typeargtypes, true, rs.resolveMethodCheck);
+                        that.expr.type, that.name, lookupArgs, typeargtypes,
+                        true, referenceCheck);
 
             Symbol refSym = refResult.fst;
             Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
@@ -2777,16 +2791,20 @@
                 }
             }
 
-            that.sym = refSym.baseSymbol();
-            that.kind = lookupHelper.referenceKind(that.sym);
-
             ResultInfo checkInfo =
                     resultInfo.dup(newMethodTemplate(
                         desc.getReturnType().hasTag(VOID) ? Type.noType : desc.getReturnType(),
-                        lookupHelper.argtypes,
+                        that.kind.isUnbound() ? argtypes.tail : argtypes,
                         typeargtypes));
 
             Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo);
+            
+            if (that.kind.isUnbound() && unstickRound) {
+                //generate inference constraints for unbound receiver
+                if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asFree(argtypes.head), exprType)) {
+                    resultInfo.checkContext.report(that, diags.fragment("inconvertible.types", argtypes.head, exprType));
+                }
+            }
 
             if (!refType.isErroneous()) {
                 refType = types.createMethodTypeWithReturn(refType,
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Thu Jun 06 16:04:38 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Fri Jun 28 11:54:17 2013 +0100
@@ -36,17 +36,16 @@
 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
 import com.sun.tools.javac.tree.JCTree.*;
 
-import javax.tools.JavaFileObject;
 
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.LinkedHashSet;
 import java.util.Map;
-import java.util.Queue;
 import java.util.Set;
 import java.util.WeakHashMap;
 
 import static com.sun.tools.javac.code.TypeTag.*;
+import com.sun.tools.javac.comp.Resolve.ReferenceLookupHelper;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /**
@@ -96,6 +95,17 @@
         types = Types.instance(context);
         Names names = Names.instance(context);
         stuckTree = make.Ident(names.empty).setType(Type.stuckType);
+        emptyDeferredAttrContext =
+            new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
+                @Override
+                void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
+                    Assert.error("Empty deferred context!");
+                }
+                @Override
+                void complete() {
+                    Assert.error("Empty deferred context!");
+                }
+            };
     }
 
     /** shared tree for stuck expressions */
@@ -474,12 +484,10 @@
 
             ResultInfo resultInfo;
             InferenceContext inferenceContext;
-            Env<AttrContext> env;
 
             public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
                 this.resultInfo = resultInfo;
-                this.inferenceContext = deferredAttrContext.inferenceContext;
-                this.env = dt.env.dup(dt.tree, dt.env.info.dup());
+                this.inferenceContext = deferredAttrContext.inferenceContext;                
                 dt.tree.accept(this);
                 dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase);
                 return Type.noType;
@@ -528,18 +536,7 @@
                     } catch (Types.FunctionDescriptorLookupError ex) {
                         checkContext.report(null, ex.getDiagnostic());
                     }
-                    JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), env,
-                            attr.memberReferenceQualifierResult(tree));
-                    ListBuffer<Type> argtypes = ListBuffer.lb();
-                    for (Type t : types.findDescriptorType(pt).getParameterTypes()) {
-                        argtypes.append(Type.noType);
-                    }
-                    JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
-                    mref2.expr = exprTree;
-                    Pair<Symbol, ?> lookupRes =
-                            rs.resolveMemberReference(tree, env, mref2, exprTree.type,
-                                tree.name, argtypes.toList(), null, true, rs.arityMethodCheck);
-                    switch (lookupRes.fst.kind) {
+                    switch (tree.sym.kind) {
                         //note: as argtypes are erroneous types, type-errors must
                         //have been caused by arity mismatch
                         case Kinds.ABSENT_MTH:
@@ -555,17 +552,7 @@
     }
 
     /** an empty deferred attribution context - all methods throw exceptions */
-    final DeferredAttrContext emptyDeferredAttrContext =
-            new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null, null, null) {
-                @Override
-                void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
-                    Assert.error("Empty deferred context!");
-                }
-                @Override
-                void complete() {
-                    Assert.error("Empty deferred context!");
-                }
-            };
+    final DeferredAttrContext emptyDeferredAttrContext;
 
     /**
      * Map a list of types possibly containing one or more deferred types
@@ -663,12 +650,12 @@
                 if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
             return List.nil();
         } else {
-            return stuckVarsInternal(tree, resultInfo.pt, resultInfo.checkContext.inferenceContext());
+            return stuckVarsInternal(tree, resultInfo.pt, env, resultInfo.checkContext.inferenceContext());
         }
     }
     //where
-        private List<Type> stuckVarsInternal(JCTree tree, Type pt, Infer.InferenceContext inferenceContext) {
-            StuckChecker sc = new StuckChecker(pt, inferenceContext);
+        private List<Type> stuckVarsInternal(JCTree tree, Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
+            StuckChecker sc = new StuckChecker(pt, env, inferenceContext);
             sc.scan(tree);
             return List.from(sc.stuckVars);
         }
@@ -748,11 +735,13 @@
     class StuckChecker extends PolyScanner {
 
         Type pt;
+        Env<AttrContext> env;
         Infer.InferenceContext inferenceContext;
         Set<Type> stuckVars = new LinkedHashSet<Type>();
 
-        StuckChecker(Type pt, Infer.InferenceContext inferenceContext) {
+        StuckChecker(Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
             this.pt = pt;
+            this.env = env;
             this.inferenceContext = inferenceContext;
         }
 
@@ -786,18 +775,40 @@
 
             Type descType = types.findDescriptorType(pt);
             List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
-            stuckVars.addAll(freeArgVars);
+            Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
+            if (freeArgVars.nonEmpty()) {
+                //perform arity-based check
+                JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
+                        attr.memberReferenceQualifierResult(tree));
+                ListBuffer<Type> argtypes = ListBuffer.lb();
+                for (Type t : descType.getParameterTypes()) {
+                    argtypes.append(Type.noType);
+                }
+                JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
+                mref2.expr = exprTree;
+                Pair<Symbol, ReferenceLookupHelper> lookupRes =
+                        rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
+                            tree.name, argtypes.toList(), null, true, rs.arityMethodCheck);
+                Symbol res = tree.sym = lookupRes.fst;
+                if (res.kind >= Kinds.ERRONEOUS ||
+                        res.type.hasTag(FORALL) ||
+                        (res.flags() & Flags.VARARGS) != 0 ||
+                        (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) &&
+                        exprTree.type.isRaw())) {
+                    stuckVars.addAll(freeArgVars);
+                }
+            }
         }
 
         void scanLambdaBody(JCLambda lambda, final Type pt) {
             if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
-                stuckVars.addAll(stuckVarsInternal(lambda.body, pt, inferenceContext));
+                stuckVars.addAll(stuckVarsInternal(lambda.body, pt, env, inferenceContext));
             } else {
                 LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
                     @Override
                     public void visitReturn(JCReturn tree) {
                         if (tree.expr != null) {
-                            stuckVars.addAll(stuckVarsInternal(tree.expr, pt, inferenceContext));
+                            stuckVars.addAll(stuckVarsInternal(tree.expr, pt, env, inferenceContext));
                         }
                     }
                 };
@@ -941,12 +952,9 @@
                     attribSpeculative(rec, env, attr.unknownTypeExprInfo).type :
                     env.enclClass.sym.type;
 
-            ListBuffer<Type> args = ListBuffer.lb();
-            for (int i = 0; i < tree.args.length(); i ++) {
-                args.append(Type.noType);
-            }
+            List<Type> args = rs.dummyArgs(tree.args.length());
 
-            Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args.toList(), List.<Type>nil(), MethodResolutionPhase.VARARITY) {
+            Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args, List.<Type>nil(), MethodResolutionPhase.VARARITY) {
                 @Override
                 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
                     return rec == null ?
--- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Jun 06 16:04:38 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Jun 28 11:54:17 2013 +0100
@@ -149,7 +149,7 @@
         inferenceException.clear();
         try {
             DeferredAttr.DeferredAttrContext deferredAttrContext =
-                    resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
+                        resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
 
             resolveContext.methodCheck.argumentsAcceptable(env, deferredAttrContext,
                     argtypes, mt.getParameterTypes(), warn);
@@ -238,32 +238,32 @@
         }
         return from;
     }
-    //where
-        private Type returnConstraintTarget(Type from, Type to) {
-            if (from.hasTag(VOID)) {
-                return syms.voidType;
-            } else if (to.hasTag(NONE)) {
-                return from.isPrimitive() ? from : syms.objectType;
-            } else if (from.hasTag(UNDETVAR) && to.isPrimitive()) {
-                if (!allowGraphInference) {
-                    //if legacy, just return boxed type
-                    return types.boxedClass(to).type;
+
+    Type returnConstraintTarget(Type from, Type to) {
+        if (from.hasTag(VOID)) {
+            return syms.voidType;
+        } else if (to.hasTag(NONE)) {
+            return from.isPrimitive() ? from : syms.objectType;
+        } else if (from.hasTag(UNDETVAR) && to.isPrimitive()) {
+            if (!allowGraphInference) {
+                //if legacy, just return boxed type
+                return types.boxedClass(to).type;
+            }
+            //if graph inference we need to skip conflicting boxed bounds...
+            UndetVar uv = (UndetVar)from;
+            for (Type t : uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) {
+                Type boundAsPrimitive = types.unboxedType(t);
+                if (boundAsPrimitive == null) continue;
+                if (types.isConvertible(boundAsPrimitive, to)) {
+                    //effectively skip return-type constraint generation (compatibility)
+                    return syms.objectType;
                 }
-                //if graph inference we need to skip conflicting boxed bounds...
-                UndetVar uv = (UndetVar)from;
-                for (Type t : uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) {
-                    Type boundAsPrimitive = types.unboxedType(t);
-                    if (boundAsPrimitive == null) continue;
-                    if (types.isConvertible(boundAsPrimitive, to)) {
-                        //effectively skip return-type constraint generation (compatibility)
-                        return syms.objectType;
-                    }
-                }
-                return types.boxedClass(to).type;
-            } else {
-                return to;
             }
+            return types.boxedClass(to).type;
+        } else {
+            return to;
         }
+    }
 
     /**
       * Infer cyclic inference variables as described in 15.12.2.8.
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Jun 06 16:04:38 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Jun 28 11:54:17 2013 +0100
@@ -584,6 +584,12 @@
         try {
             currentResolutionContext = new MethodResolutionContext();
             currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK;
+            if (env.tree.getTag() == JCTree.Tag.REFERENCE) {
+                //method/constructor references need special check class
+                //to handle inference variables in 'argtypes' (might happen
+                //during an unsticking round)
+                currentResolutionContext.methodCheck = methodReferenceCheck;
+            }
             MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase;
             return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
                     step.isBoxingRequired(), step.isVarargsRequired(), warn);
@@ -772,6 +778,14 @@
             //do nothing - actual always compatible to formals
         }
     };
+    
+    List<Type> dummyArgs(int length) {
+        ListBuffer<Type> buf = ListBuffer.lb();
+        for (int i = 0 ; i < length ; i++) {
+            buf.append(Type.noType);
+        }
+        return buf.toList();
+    }
 
     /**
      * Main method applicability routine. Given a list of actual types A,
@@ -849,6 +863,51 @@
             return new MostSpecificCheck(strict, actuals);
         }
     };
+    
+    MethodCheck methodReferenceCheck = new AbstractMethodCheck() {
+
+        @Override
+        void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
+            ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn);
+            mresult.check(pos, actual);
+        }
+
+        @Override
+        public void argumentsAcceptable(final Env<AttrContext> env,
+                                    DeferredAttrContext deferredAttrContext,
+                                    List<Type> argtypes,
+                                    List<Type> formals,
+                                    Warner warn) {
+            super.argumentsAcceptable(env, deferredAttrContext, argtypes, formals, warn);
+            //TODO: should we propagate constraints?
+        }
+
+        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 boolean compatible(Type found, Type req, Warner warn) {
+                    found = deferredAttrContext.parent.inferenceContext.asFree(found);
+                    req = infer.returnConstraintTarget(found, req);
+                    return super.compatible(found, req, warn);
+                }
+
+                @Override
+                public void report(DiagnosticPosition pos, JCDiagnostic details) {
+                    reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details);
+                }
+            };
+            return new MethodResultInfo(to, checkContext);
+        }
+
+        @Override
+        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+            return new MostSpecificCheck(strict, actuals);
+        }
+    };
 
     /**
      * Check context to be used during method applicability checks. A method check
@@ -2579,7 +2638,7 @@
      * and T is the type of the class in which S is defined. This is necessary as
      * the type T might be dynamically inferred (i.e. if constructor reference
      * has a raw qualifier).
-     */
+     */                           
     Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos,
                                   Env<AttrContext> env,
                                   JCMemberReference referenceTree,
@@ -2815,7 +2874,7 @@
 
         UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
                 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
-            super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase);
+            super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase);            
             if (site.isRaw() && !argtypes.head.hasTag(NONE)) {
                 Type asSuperSite = types.asSuper(argtypes.head, site.tsym);
                 this.site = asSuperSite;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference68.java	Fri Jun 28 11:54:17 2013 +0100
@@ -0,0 +1,23 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8016175
+ * @summary Add bottom-up type-checking support for unambiguous method references
+ * @compile/fail/ref=MethodReference68.out -XDrawDiagnostics MethodReference68.java
+ */
+class MethodReference68 {
+    interface F<X> {
+       String m(X x);
+    }
+
+    static class Foo {
+        String getName() { return ""; }
+    }
+
+    @SuppressWarnings("unchecked")
+    <Z> void g(F<Z> fz, Z... zs) { }
+
+    void test() {
+         g(Foo::getName);
+         g(Foo::getName, 1); //incompatible constraints, Z <: Foo, Z :> Integer
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference68.out	Fri Jun 28 11:54:17 2013 +0100
@@ -0,0 +1,2 @@
+MethodReference68.java:21:10: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference68.F<Z>,Z[], @493,int, kindname.class, MethodReference68, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, MethodReference68.Foo,java.lang.Object)
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference69.java	Fri Jun 28 11:54:17 2013 +0100
@@ -0,0 +1,21 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8016175
+ * @summary Add bottom-up type-checking support for unambiguous method references
+ * @compile/fail/ref=MethodReference69.out -XDrawDiagnostics MethodReference69.java
+ */
+class MethodReference69 {
+    interface F<X> {
+        String m(Integer x1, X x2);
+    }
+
+    static class Foo {
+        String getNameAt(Integer i) { return ""; }
+    }
+
+    <Z> void g(F<Z> fz) { }
+
+    void test() {
+         g(Foo::getName);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference69.out	Fri Jun 28 11:54:17 2013 +0100
@@ -0,0 +1,2 @@
+MethodReference69.java:19:12: compiler.err.invalid.mref: kindname.method, (compiler.misc.cant.resolve.location.args: kindname.method, getName, , , (compiler.misc.location: kindname.class, MethodReference69.Foo, null))
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference70.java	Fri Jun 28 11:54:17 2013 +0100
@@ -0,0 +1,28 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8016175
+ * @summary Add bottom-up type-checking support for unambiguous method references
+ * @compile/fail/ref=MethodReference70.out -XDrawDiagnostics MethodReference70.java
+ */
+class MethodReference70 {
+    interface F<X> {
+        void m(X x);
+    }
+    
+    interface G<X> {
+        Integer m(X x);
+    }
+    
+    void m1(Integer i) { }
+    
+    void m2(Integer i) { }
+    void m2(String i) { }
+
+    <Z> void g(F<Z> fz) { }
+    <Z> void g(G<Z> gz) { }
+
+    void test() {
+         g(this::m1); //ok
+         g(this::m2); //ambiguous (stuck!)
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference70.out	Fri Jun 28 11:54:17 2013 +0100
@@ -0,0 +1,3 @@
+MethodReference70.java:26:10: compiler.err.ref.ambiguous: g, kindname.method, <Z>g(MethodReference70.F<Z>), MethodReference70, kindname.method, <Z>g(MethodReference70.G<Z>), MethodReference70
+MethodReference70.java:26:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z)
+2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference71.java	Fri Jun 28 11:54:17 2013 +0100
@@ -0,0 +1,26 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8016175
+ * @summary Add bottom-up type-checking support for unambiguous method references
+ * @compile/fail/ref=MethodReference71.out -XDrawDiagnostics MethodReference71.java
+ */
+class MethodReference71 {
+    interface F<X> {
+        void m(X x);
+    }
+    
+    interface G<X> {
+        Integer m(X x);
+    }
+    
+    void m1(Integer i) { }
+    void m2(Integer... i) { }
+
+    <Z> void g(F<Z> f) { }
+    <Z> void g(G<Z> g) { }
+
+    void test() {
+         g(this::m1); //ok
+         g(this::m2); //ambiguous (stuck!)
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference71.out	Fri Jun 28 11:54:17 2013 +0100
@@ -0,0 +1,3 @@
+MethodReference71.java:24:10: compiler.err.ref.ambiguous: g, kindname.method, <Z>g(MethodReference71.F<Z>), MethodReference71, kindname.method, <Z>g(MethodReference71.G<Z>), MethodReference71
+MethodReference71.java:24:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z)
+2 errors
--- a/test/tools/javac/lambda/TargetType60.out	Thu Jun 06 16:04:38 2013 +0100
+++ b/test/tools/javac/lambda/TargetType60.out	Fri Jun 28 11:54:17 2013 +0100
@@ -1,7 +1,7 @@
 TargetType60.java:54:21: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType60.Sam0), TargetType60, kindname.method, <U>g(TargetType60.Sam1<U>), TargetType60
 TargetType60.java:55:21: compiler.err.ref.ambiguous: g, kindname.method, <U>g(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>g(TargetType60.Sam2<U,java.lang.String>), TargetType60
 TargetType60.java:60:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
-TargetType60.java:60:28: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: U, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, n1, java.lang.String, TargetType60, kindname.class, TargetType60, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: TargetType60, java.lang.String)))))
+TargetType60.java:60:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n1(java.lang.String))
 TargetType60.java:61:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n2(TargetType60,java.lang.String))
 TargetType60.java:62:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
 TargetType60.java:63:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60