# HG changeset patch # User mcimadamore # Date 1374066586 -3600 # Node ID 866c87c01285cff06267e1d20e21f1982421d37f # Parent 44e27378f523bdc1d06cc87e7c94bef2c808cf7a 8016175: Add bottom-up type-checking support for unambiguous method references Summary: Type-checking of non-overloaded method references should be independent from target-type Reviewed-by: jjg, vromero diff -r 44e27378f523 -r 866c87c01285 src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 17 14:04:01 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 17 14:09:46 2013 +0100 @@ -2708,10 +2708,21 @@ setFunctionalInfo(that, pt(), desc, target, resultInfo.checkContext.inferenceContext()); List argtypes = desc.getParameterTypes(); - - Pair refResult = - rs.resolveMemberReference(that.pos(), localEnv, that, - that.expr.type, that.name, argtypes, typeargtypes, true, rs.resolveMethodCheck); + Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck; + + if (resultInfo.checkContext.inferenceContext().free(argtypes)) { + referenceCheck = rs.new MethodReferenceCheck(resultInfo.checkContext.inferenceContext()); + } + + Pair refResult = null; + List saved_undet = resultInfo.checkContext.inferenceContext().save(); + try { + refResult = rs.resolveMemberReference(that.pos(), localEnv, that, that.expr.type, + that.name, argtypes, typeargtypes, true, referenceCheck, + resultInfo.checkContext.inferenceContext()); + } finally { + resultInfo.checkContext.inferenceContext().rollback(saved_undet); + } Symbol refSym = refResult.fst; Resolve.ReferenceLookupHelper lookupHelper = refResult.snd; @@ -2823,17 +2834,24 @@ } } - 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, - typeargtypes)); + that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes)); Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo); + if (that.kind.isUnbound() && + resultInfo.checkContext.inferenceContext().free(argtypes.head)) { + //re-generate inference constraints for unbound receiver + if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asFree(argtypes.head), exprType)) { + //cannot happen as this has already been checked - we just need + //to regenerate the inference constraints, as that has been lost + //as a result of the call to inferenceContext.save() + Assert.error("Can't get here"); + } + } + if (!refType.isErroneous()) { refType = types.createMethodTypeWithReturn(refType, adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType())); diff -r 44e27378f523 -r 866c87c01285 src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java --- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Jul 17 14:04:01 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Jul 17 14:09:46 2013 +0100 @@ -34,15 +34,14 @@ import com.sun.tools.javac.comp.Attr.ResultInfo; import com.sun.tools.javac.comp.Infer.InferenceContext; import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; +import com.sun.tools.javac.comp.Resolve.ReferenceLookupHelper; import com.sun.tools.javac.tree.JCTree.*; -import 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; @@ -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 stuckVars) { + Assert.error("Empty deferred context!"); + } + @Override + void complete() { + Assert.error("Empty deferred context!"); + } + }; } /** shared tree for stuck expressions */ @@ -479,12 +489,10 @@ ResultInfo resultInfo; InferenceContext inferenceContext; - Env 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()); dt.tree.accept(this); dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase); return Type.noType; @@ -533,18 +541,7 @@ } catch (Types.FunctionDescriptorLookupError ex) { checkContext.report(null, ex.getDiagnostic()); } - JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), env, - attr.memberReferenceQualifierResult(tree)); - ListBuffer argtypes = ListBuffer.lb(); - for (Type t : types.findDescriptorType(pt).getParameterTypes()) { - argtypes.append(Type.noType); - } - JCMemberReference mref2 = new TreeCopier(make).copy(tree); - mref2.expr = exprTree; - Pair 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: @@ -560,17 +557,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 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 @@ -668,12 +655,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 stuckVarsInternal(JCTree tree, Type pt, Infer.InferenceContext inferenceContext) { - StuckChecker sc = new StuckChecker(pt, inferenceContext); + private List stuckVarsInternal(JCTree tree, Type pt, Env env, Infer.InferenceContext inferenceContext) { + StuckChecker sc = new StuckChecker(pt, env, inferenceContext); sc.scan(tree); return List.from(sc.stuckVars); } @@ -753,11 +740,13 @@ class StuckChecker extends PolyScanner { Type pt; + Env env; Infer.InferenceContext inferenceContext; Set stuckVars = new LinkedHashSet(); - StuckChecker(Type pt, Infer.InferenceContext inferenceContext) { + StuckChecker(Type pt, Env env, Infer.InferenceContext inferenceContext) { this.pt = pt; + this.env = env; this.inferenceContext = inferenceContext; } @@ -791,18 +780,41 @@ Type descType = types.findDescriptorType(pt); List freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); - stuckVars.addAll(freeArgVars); + Env 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 argtypes = ListBuffer.lb(); + for (Type t : descType.getParameterTypes()) { + argtypes.append(Type.noType); + } + JCMemberReference mref2 = new TreeCopier(make).copy(tree); + mref2.expr = exprTree; + Pair lookupRes = + rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type, + tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, + inferenceContext); + 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)); } } }; @@ -950,12 +962,9 @@ site = site.getUpperBound(); } - ListBuffer args = ListBuffer.lb(); - for (int i = 0; i < tree.args.length(); i ++) { - args.append(Type.noType); - } + List args = rs.dummyArgs(tree.args.length()); - Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args.toList(), List.nil(), MethodResolutionPhase.VARARITY) { + Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args, List.nil(), MethodResolutionPhase.VARARITY) { @Override Symbol lookup(Env env, MethodResolutionPhase phase) { return rec == null ? diff -r 44e27378f523 -r 866c87c01285 src/share/classes/com/sun/tools/javac/comp/Infer.java --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Jul 17 14:04:01 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Jul 17 14:09:46 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); @@ -225,32 +225,32 @@ inferenceContext.restvars(), mt.getReturnType(), to); } } - //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. @@ -1337,9 +1337,6 @@ /** list of inference vars in this context */ List inferencevars; - /** backed up inference variables */ - List saved_undet; - java.util.Map> freeTypeListeners = new java.util.HashMap>(); diff -r 44e27378f523 -r 866c87c01285 src/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 17 14:04:01 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 17 14:09:46 2013 +0100 @@ -584,6 +584,13 @@ try { currentResolutionContext = new MethodResolutionContext(); currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK; + if (env.tree.hasTag(JCTree.Tag.REFERENCE)) { + //method/constructor references need special check class + //to handle inference variables in 'argtypes' (might happen + //during an unsticking round) + currentResolutionContext.methodCheck = + new MethodReferenceCheck(resultInfo.checkContext.inferenceContext()); + } MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase; return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, step.isBoxingRequired(), step.isVarargsRequired(), warn); @@ -773,6 +780,14 @@ } }; + List dummyArgs(int length) { + ListBuffer 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, * a list of formal types F, determines whether the types in A are @@ -850,6 +865,47 @@ } }; + class MethodReferenceCheck extends AbstractMethodCheck { + + InferenceContext pendingInferenceContext; + + MethodReferenceCheck(InferenceContext pendingInferenceContext) { + this.pendingInferenceContext = pendingInferenceContext; + } + + @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); + } + + 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 = pendingInferenceContext.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 actuals, boolean strict) { + return new MostSpecificCheck(strict, actuals); + } + }; + /** * Check context to be used during method applicability checks. A method check * context might contain inference variables. @@ -2576,7 +2632,8 @@ Name name, List argtypes, List typeargtypes, boolean boxingAllowed, - MethodCheck methodCheck) { + MethodCheck methodCheck, + InferenceContext inferenceContext) { MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; ReferenceLookupHelper boundLookupHelper; @@ -2599,7 +2656,7 @@ Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper); //step 2 - unbound lookup - ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(); + ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext); Env unboundEnv = env.dup(env.tree, env.info.dup()); Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper); @@ -2739,11 +2796,11 @@ * Returns an unbound version of this lookup helper. By default, this * method returns an dummy lookup helper. */ - ReferenceLookupHelper unboundLookup() { + ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { //dummy loopkup helper that always return 'methodNotFound' return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) { @Override - ReferenceLookupHelper unboundLookup() { + ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { return this; } @Override @@ -2793,14 +2850,15 @@ } @Override - ReferenceLookupHelper unboundLookup() { + ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { if (TreeInfo.isStaticSelector(referenceTree.expr, names) && argtypes.nonEmpty() && - (argtypes.head.hasTag(NONE) || types.isSubtypeUnchecked(argtypes.head, site))) { + (argtypes.head.hasTag(NONE) || + types.isSubtypeUnchecked(inferenceContext.asFree(argtypes.head), site))) { return new UnboundMethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); } else { - return super.unboundLookup(); + return super.unboundLookup(inferenceContext); } } @@ -2836,7 +2894,7 @@ } @Override - ReferenceLookupHelper unboundLookup() { + ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { return this; } diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference68.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference68.java Wed Jul 17 14:09:46 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 { + String m(X x); + } + + static class Foo { + String getName() { return ""; } + } + + @SuppressWarnings("unchecked") + void g(F fz, Z... zs) { } + + void test() { + g(Foo::getName); + g(Foo::getName, 1); //incompatible constraints, Z <: Foo, Z :> Integer + } +} diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference68.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference68.out Wed Jul 17 14:09:46 2013 +0100 @@ -0,0 +1,2 @@ +MethodReference68.java:21:10: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference68.F,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 diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference69.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference69.java Wed Jul 17 14:09:46 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 { + String m(Integer x1, X x2); + } + + static class Foo { + String getNameAt(Integer i) { return ""; } + } + + void g(F fz) { } + + void test() { + g(Foo::getName); + } +} diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference69.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference69.out Wed Jul 17 14:09:46 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 diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference70.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference70.java Wed Jul 17 14:09:46 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 { + void m(X x); + } + + interface G { + Integer m(X x); + } + + void m1(Integer i) { } + + void m2(Integer i) { } + void m2(String i) { } + + void g(F fz) { } + void g(G gz) { } + + void test() { + g(this::m1); //ok + g(this::m2); //ambiguous (stuck!) + } +} diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference70.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference70.out Wed Jul 17 14:09:46 2013 +0100 @@ -0,0 +1,3 @@ +MethodReference70.java:26:10: compiler.err.ref.ambiguous: g, kindname.method, g(MethodReference70.F), MethodReference70, kindname.method, g(MethodReference70.G), MethodReference70 +MethodReference70.java:26:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z) +2 errors diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference71.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference71.java Wed Jul 17 14:09:46 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 { + void m(X x); + } + + interface G { + Integer m(X x); + } + + void m1(Integer i) { } + void m2(Integer... i) { } + + void g(F f) { } + void g(G g) { } + + void test() { + g(this::m1); //ok + g(this::m2); //ambiguous (stuck!) + } +} diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference71.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference71.out Wed Jul 17 14:09:46 2013 +0100 @@ -0,0 +1,3 @@ +MethodReference71.java:24:10: compiler.err.ref.ambiguous: g, kindname.method, g(MethodReference71.F), MethodReference71, kindname.method, g(MethodReference71.G), MethodReference71 +MethodReference71.java:24:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z) +2 errors diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference72.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference72.java Wed Jul 17 14:09:46 2013 +0100 @@ -0,0 +1,20 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8016175 + * @summary Add bottom-up type-checking support for unambiguous method references + * @compile/fail/ref=MethodReference72.out -XDrawDiagnostics MethodReference72.java + */ +class MethodReference72 { + interface F { + @SuppressWarnings("unchecked") + void m(X... x); + } + + void m1(Integer i) { } + + void g(F f) { } + + void test() { + g(this::m1); //? + } +} diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/MethodReference72.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference72.out Wed Jul 17 14:09:46 2013 +0100 @@ -0,0 +1,2 @@ +MethodReference72.java:18:9: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference72.F, @420, kindname.class, MethodReference72, (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m1, java.lang.Integer, Z[], kindname.class, MethodReference72, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: Z[], java.lang.Integer))))) +1 error diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/TargetType60.out --- a/test/tools/javac/lambda/TargetType60.out Wed Jul 17 14:04:01 2013 +0100 +++ b/test/tools/javac/lambda/TargetType60.out Wed Jul 17 14:09:46 2013 +0100 @@ -1,7 +1,7 @@ TargetType60.java:54:21: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType60.Sam0), TargetType60, kindname.method, g(TargetType60.Sam1), TargetType60 TargetType60.java:55:21: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType60.Sam1), TargetType60, kindname.method, g(TargetType60.Sam2), TargetType60 TargetType60.java:60:27: compiler.err.ref.ambiguous: u, kindname.method, u(TargetType60.Sam1), TargetType60, kindname.method, u(TargetType60.Sam2), 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(TargetType60.Sam1), TargetType60, kindname.method, u(TargetType60.Sam2), TargetType60 TargetType60.java:63:27: compiler.err.ref.ambiguous: u, kindname.method, u(TargetType60.Sam1), TargetType60, kindname.method, u(TargetType60.Sam2), TargetType60 diff -r 44e27378f523 -r 866c87c01285 test/tools/javac/lambda/TargetType76.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/TargetType76.java Wed Jul 17 14:09:46 2013 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8016175 + * @summary Add bottom-up type-checking support for unambiguous method references + * @compile TargetType76.java + */ +class TargetType76 { + + interface Function { + Y m(X x); + } + + interface OfRef { } + + interface Supplier { + X make(); + } + + interface Stream { } + + interface Node { + Spliterator spliterator(); + } + + interface Spliterator { + Spliterator spliterator(); + } + + class RefTestData implements OfRef { + RefTestData(I state, + Function> streamFn, + Function> splitrFn) { } + } + + OfRef ofCollection(Node collection) { + return new RefTestData<>(collection, + x->stream(x::spliterator), + Node::spliterator); + } + + Stream stream(Supplier> supplier) { return null; } +}