Wed, 17 Jul 2013 14:09:46 +0100
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
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 17 14:04:01 2013 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 17 14:09:46 2013 +0100 1.3 @@ -2708,10 +2708,21 @@ 1.4 1.5 setFunctionalInfo(that, pt(), desc, target, resultInfo.checkContext.inferenceContext()); 1.6 List<Type> argtypes = desc.getParameterTypes(); 1.7 - 1.8 - Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = 1.9 - rs.resolveMemberReference(that.pos(), localEnv, that, 1.10 - that.expr.type, that.name, argtypes, typeargtypes, true, rs.resolveMethodCheck); 1.11 + Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck; 1.12 + 1.13 + if (resultInfo.checkContext.inferenceContext().free(argtypes)) { 1.14 + referenceCheck = rs.new MethodReferenceCheck(resultInfo.checkContext.inferenceContext()); 1.15 + } 1.16 + 1.17 + Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = null; 1.18 + List<Type> saved_undet = resultInfo.checkContext.inferenceContext().save(); 1.19 + try { 1.20 + refResult = rs.resolveMemberReference(that.pos(), localEnv, that, that.expr.type, 1.21 + that.name, argtypes, typeargtypes, true, referenceCheck, 1.22 + resultInfo.checkContext.inferenceContext()); 1.23 + } finally { 1.24 + resultInfo.checkContext.inferenceContext().rollback(saved_undet); 1.25 + } 1.26 1.27 Symbol refSym = refResult.fst; 1.28 Resolve.ReferenceLookupHelper lookupHelper = refResult.snd; 1.29 @@ -2823,17 +2834,24 @@ 1.30 } 1.31 } 1.32 1.33 - that.sym = refSym.baseSymbol(); 1.34 - that.kind = lookupHelper.referenceKind(that.sym); 1.35 - 1.36 ResultInfo checkInfo = 1.37 resultInfo.dup(newMethodTemplate( 1.38 desc.getReturnType().hasTag(VOID) ? Type.noType : desc.getReturnType(), 1.39 - lookupHelper.argtypes, 1.40 - typeargtypes)); 1.41 + that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes)); 1.42 1.43 Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo); 1.44 1.45 + if (that.kind.isUnbound() && 1.46 + resultInfo.checkContext.inferenceContext().free(argtypes.head)) { 1.47 + //re-generate inference constraints for unbound receiver 1.48 + if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asFree(argtypes.head), exprType)) { 1.49 + //cannot happen as this has already been checked - we just need 1.50 + //to regenerate the inference constraints, as that has been lost 1.51 + //as a result of the call to inferenceContext.save() 1.52 + Assert.error("Can't get here"); 1.53 + } 1.54 + } 1.55 + 1.56 if (!refType.isErroneous()) { 1.57 refType = types.createMethodTypeWithReturn(refType, 1.58 adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Jul 17 14:04:01 2013 +0100 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Jul 17 14:09:46 2013 +0100 2.3 @@ -34,15 +34,14 @@ 2.4 import com.sun.tools.javac.comp.Attr.ResultInfo; 2.5 import com.sun.tools.javac.comp.Infer.InferenceContext; 2.6 import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; 2.7 +import com.sun.tools.javac.comp.Resolve.ReferenceLookupHelper; 2.8 import com.sun.tools.javac.tree.JCTree.*; 2.9 2.10 -import javax.tools.JavaFileObject; 2.11 2.12 import java.util.ArrayList; 2.13 import java.util.EnumSet; 2.14 import java.util.LinkedHashSet; 2.15 import java.util.Map; 2.16 -import java.util.Queue; 2.17 import java.util.Set; 2.18 import java.util.WeakHashMap; 2.19 2.20 @@ -96,6 +95,17 @@ 2.21 types = Types.instance(context); 2.22 Names names = Names.instance(context); 2.23 stuckTree = make.Ident(names.empty).setType(Type.stuckType); 2.24 + emptyDeferredAttrContext = 2.25 + new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) { 2.26 + @Override 2.27 + void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) { 2.28 + Assert.error("Empty deferred context!"); 2.29 + } 2.30 + @Override 2.31 + void complete() { 2.32 + Assert.error("Empty deferred context!"); 2.33 + } 2.34 + }; 2.35 } 2.36 2.37 /** shared tree for stuck expressions */ 2.38 @@ -479,12 +489,10 @@ 2.39 2.40 ResultInfo resultInfo; 2.41 InferenceContext inferenceContext; 2.42 - Env<AttrContext> env; 2.43 2.44 public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 2.45 this.resultInfo = resultInfo; 2.46 this.inferenceContext = deferredAttrContext.inferenceContext; 2.47 - this.env = dt.env.dup(dt.tree, dt.env.info.dup()); 2.48 dt.tree.accept(this); 2.49 dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase); 2.50 return Type.noType; 2.51 @@ -533,18 +541,7 @@ 2.52 } catch (Types.FunctionDescriptorLookupError ex) { 2.53 checkContext.report(null, ex.getDiagnostic()); 2.54 } 2.55 - JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), env, 2.56 - attr.memberReferenceQualifierResult(tree)); 2.57 - ListBuffer<Type> argtypes = ListBuffer.lb(); 2.58 - for (Type t : types.findDescriptorType(pt).getParameterTypes()) { 2.59 - argtypes.append(Type.noType); 2.60 - } 2.61 - JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree); 2.62 - mref2.expr = exprTree; 2.63 - Pair<Symbol, ?> lookupRes = 2.64 - rs.resolveMemberReference(tree, env, mref2, exprTree.type, 2.65 - tree.name, argtypes.toList(), null, true, rs.arityMethodCheck); 2.66 - switch (lookupRes.fst.kind) { 2.67 + switch (tree.sym.kind) { 2.68 //note: as argtypes are erroneous types, type-errors must 2.69 //have been caused by arity mismatch 2.70 case Kinds.ABSENT_MTH: 2.71 @@ -560,17 +557,7 @@ 2.72 } 2.73 2.74 /** an empty deferred attribution context - all methods throw exceptions */ 2.75 - final DeferredAttrContext emptyDeferredAttrContext = 2.76 - new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null, null, null) { 2.77 - @Override 2.78 - void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) { 2.79 - Assert.error("Empty deferred context!"); 2.80 - } 2.81 - @Override 2.82 - void complete() { 2.83 - Assert.error("Empty deferred context!"); 2.84 - } 2.85 - }; 2.86 + final DeferredAttrContext emptyDeferredAttrContext; 2.87 2.88 /** 2.89 * Map a list of types possibly containing one or more deferred types 2.90 @@ -668,12 +655,12 @@ 2.91 if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) { 2.92 return List.nil(); 2.93 } else { 2.94 - return stuckVarsInternal(tree, resultInfo.pt, resultInfo.checkContext.inferenceContext()); 2.95 + return stuckVarsInternal(tree, resultInfo.pt, env, resultInfo.checkContext.inferenceContext()); 2.96 } 2.97 } 2.98 //where 2.99 - private List<Type> stuckVarsInternal(JCTree tree, Type pt, Infer.InferenceContext inferenceContext) { 2.100 - StuckChecker sc = new StuckChecker(pt, inferenceContext); 2.101 + private List<Type> stuckVarsInternal(JCTree tree, Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) { 2.102 + StuckChecker sc = new StuckChecker(pt, env, inferenceContext); 2.103 sc.scan(tree); 2.104 return List.from(sc.stuckVars); 2.105 } 2.106 @@ -753,11 +740,13 @@ 2.107 class StuckChecker extends PolyScanner { 2.108 2.109 Type pt; 2.110 + Env<AttrContext> env; 2.111 Infer.InferenceContext inferenceContext; 2.112 Set<Type> stuckVars = new LinkedHashSet<Type>(); 2.113 2.114 - StuckChecker(Type pt, Infer.InferenceContext inferenceContext) { 2.115 + StuckChecker(Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) { 2.116 this.pt = pt; 2.117 + this.env = env; 2.118 this.inferenceContext = inferenceContext; 2.119 } 2.120 2.121 @@ -791,18 +780,41 @@ 2.122 2.123 Type descType = types.findDescriptorType(pt); 2.124 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); 2.125 - stuckVars.addAll(freeArgVars); 2.126 + Env<AttrContext> localEnv = env.dup(tree, env.info.dup()); 2.127 + if (freeArgVars.nonEmpty()) { 2.128 + //perform arity-based check 2.129 + JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, 2.130 + attr.memberReferenceQualifierResult(tree)); 2.131 + ListBuffer<Type> argtypes = ListBuffer.lb(); 2.132 + for (Type t : descType.getParameterTypes()) { 2.133 + argtypes.append(Type.noType); 2.134 + } 2.135 + JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree); 2.136 + mref2.expr = exprTree; 2.137 + Pair<Symbol, ReferenceLookupHelper> lookupRes = 2.138 + rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type, 2.139 + tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, 2.140 + inferenceContext); 2.141 + Symbol res = tree.sym = lookupRes.fst; 2.142 + if (res.kind >= Kinds.ERRONEOUS || 2.143 + res.type.hasTag(FORALL) || 2.144 + (res.flags() & Flags.VARARGS) != 0 || 2.145 + (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && 2.146 + exprTree.type.isRaw())) { 2.147 + stuckVars.addAll(freeArgVars); 2.148 + } 2.149 + } 2.150 } 2.151 2.152 void scanLambdaBody(JCLambda lambda, final Type pt) { 2.153 if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { 2.154 - stuckVars.addAll(stuckVarsInternal(lambda.body, pt, inferenceContext)); 2.155 + stuckVars.addAll(stuckVarsInternal(lambda.body, pt, env, inferenceContext)); 2.156 } else { 2.157 LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() { 2.158 @Override 2.159 public void visitReturn(JCReturn tree) { 2.160 if (tree.expr != null) { 2.161 - stuckVars.addAll(stuckVarsInternal(tree.expr, pt, inferenceContext)); 2.162 + stuckVars.addAll(stuckVarsInternal(tree.expr, pt, env, inferenceContext)); 2.163 } 2.164 } 2.165 }; 2.166 @@ -950,12 +962,9 @@ 2.167 site = site.getUpperBound(); 2.168 } 2.169 2.170 - ListBuffer<Type> args = ListBuffer.lb(); 2.171 - for (int i = 0; i < tree.args.length(); i ++) { 2.172 - args.append(Type.noType); 2.173 - } 2.174 + List<Type> args = rs.dummyArgs(tree.args.length()); 2.175 2.176 - Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args.toList(), List.<Type>nil(), MethodResolutionPhase.VARARITY) { 2.177 + Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args, List.<Type>nil(), MethodResolutionPhase.VARARITY) { 2.178 @Override 2.179 Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 2.180 return rec == null ?
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Jul 17 14:04:01 2013 +0100 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Jul 17 14:09:46 2013 +0100 3.3 @@ -149,7 +149,7 @@ 3.4 inferenceException.clear(); 3.5 try { 3.6 DeferredAttr.DeferredAttrContext deferredAttrContext = 3.7 - resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn); 3.8 + resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn); 3.9 3.10 resolveContext.methodCheck.argumentsAcceptable(env, deferredAttrContext, 3.11 argtypes, mt.getParameterTypes(), warn); 3.12 @@ -225,32 +225,32 @@ 3.13 inferenceContext.restvars(), mt.getReturnType(), to); 3.14 } 3.15 } 3.16 - //where 3.17 - private Type returnConstraintTarget(Type from, Type to) { 3.18 - if (from.hasTag(VOID)) { 3.19 - return syms.voidType; 3.20 - } else if (to.hasTag(NONE)) { 3.21 - return from.isPrimitive() ? from : syms.objectType; 3.22 - } else if (from.hasTag(UNDETVAR) && to.isPrimitive()) { 3.23 - if (!allowGraphInference) { 3.24 - //if legacy, just return boxed type 3.25 - return types.boxedClass(to).type; 3.26 + 3.27 + Type returnConstraintTarget(Type from, Type to) { 3.28 + if (from.hasTag(VOID)) { 3.29 + return syms.voidType; 3.30 + } else if (to.hasTag(NONE)) { 3.31 + return from.isPrimitive() ? from : syms.objectType; 3.32 + } else if (from.hasTag(UNDETVAR) && to.isPrimitive()) { 3.33 + if (!allowGraphInference) { 3.34 + //if legacy, just return boxed type 3.35 + return types.boxedClass(to).type; 3.36 + } 3.37 + //if graph inference we need to skip conflicting boxed bounds... 3.38 + UndetVar uv = (UndetVar)from; 3.39 + for (Type t : uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { 3.40 + Type boundAsPrimitive = types.unboxedType(t); 3.41 + if (boundAsPrimitive == null) continue; 3.42 + if (types.isConvertible(boundAsPrimitive, to)) { 3.43 + //effectively skip return-type constraint generation (compatibility) 3.44 + return syms.objectType; 3.45 } 3.46 - //if graph inference we need to skip conflicting boxed bounds... 3.47 - UndetVar uv = (UndetVar)from; 3.48 - for (Type t : uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { 3.49 - Type boundAsPrimitive = types.unboxedType(t); 3.50 - if (boundAsPrimitive == null) continue; 3.51 - if (types.isConvertible(boundAsPrimitive, to)) { 3.52 - //effectively skip return-type constraint generation (compatibility) 3.53 - return syms.objectType; 3.54 - } 3.55 - } 3.56 - return types.boxedClass(to).type; 3.57 - } else { 3.58 - return to; 3.59 } 3.60 + return types.boxedClass(to).type; 3.61 + } else { 3.62 + return to; 3.63 } 3.64 + } 3.65 3.66 /** 3.67 * Infer cyclic inference variables as described in 15.12.2.8. 3.68 @@ -1337,9 +1337,6 @@ 3.69 /** list of inference vars in this context */ 3.70 List<Type> inferencevars; 3.71 3.72 - /** backed up inference variables */ 3.73 - List<Type> saved_undet; 3.74 - 3.75 java.util.Map<FreeTypeListener, List<Type>> freeTypeListeners = 3.76 new java.util.HashMap<FreeTypeListener, List<Type>>(); 3.77
4.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 17 14:04:01 2013 +0100 4.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 17 14:09:46 2013 +0100 4.3 @@ -584,6 +584,13 @@ 4.4 try { 4.5 currentResolutionContext = new MethodResolutionContext(); 4.6 currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK; 4.7 + if (env.tree.hasTag(JCTree.Tag.REFERENCE)) { 4.8 + //method/constructor references need special check class 4.9 + //to handle inference variables in 'argtypes' (might happen 4.10 + //during an unsticking round) 4.11 + currentResolutionContext.methodCheck = 4.12 + new MethodReferenceCheck(resultInfo.checkContext.inferenceContext()); 4.13 + } 4.14 MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase; 4.15 return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 4.16 step.isBoxingRequired(), step.isVarargsRequired(), warn); 4.17 @@ -773,6 +780,14 @@ 4.18 } 4.19 }; 4.20 4.21 + List<Type> dummyArgs(int length) { 4.22 + ListBuffer<Type> buf = ListBuffer.lb(); 4.23 + for (int i = 0 ; i < length ; i++) { 4.24 + buf.append(Type.noType); 4.25 + } 4.26 + return buf.toList(); 4.27 + } 4.28 + 4.29 /** 4.30 * Main method applicability routine. Given a list of actual types A, 4.31 * a list of formal types F, determines whether the types in A are 4.32 @@ -850,6 +865,47 @@ 4.33 } 4.34 }; 4.35 4.36 + class MethodReferenceCheck extends AbstractMethodCheck { 4.37 + 4.38 + InferenceContext pendingInferenceContext; 4.39 + 4.40 + MethodReferenceCheck(InferenceContext pendingInferenceContext) { 4.41 + this.pendingInferenceContext = pendingInferenceContext; 4.42 + } 4.43 + 4.44 + @Override 4.45 + void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 4.46 + ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn); 4.47 + mresult.check(pos, actual); 4.48 + } 4.49 + 4.50 + private ResultInfo methodCheckResult(final boolean varargsCheck, Type to, 4.51 + final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) { 4.52 + CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) { 4.53 + MethodCheckDiag methodDiag = varargsCheck ? 4.54 + MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH; 4.55 + 4.56 + @Override 4.57 + public boolean compatible(Type found, Type req, Warner warn) { 4.58 + found = pendingInferenceContext.asFree(found); 4.59 + req = infer.returnConstraintTarget(found, req); 4.60 + return super.compatible(found, req, warn); 4.61 + } 4.62 + 4.63 + @Override 4.64 + public void report(DiagnosticPosition pos, JCDiagnostic details) { 4.65 + reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details); 4.66 + } 4.67 + }; 4.68 + return new MethodResultInfo(to, checkContext); 4.69 + } 4.70 + 4.71 + @Override 4.72 + public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) { 4.73 + return new MostSpecificCheck(strict, actuals); 4.74 + } 4.75 + }; 4.76 + 4.77 /** 4.78 * Check context to be used during method applicability checks. A method check 4.79 * context might contain inference variables. 4.80 @@ -2576,7 +2632,8 @@ 4.81 Name name, List<Type> argtypes, 4.82 List<Type> typeargtypes, 4.83 boolean boxingAllowed, 4.84 - MethodCheck methodCheck) { 4.85 + MethodCheck methodCheck, 4.86 + InferenceContext inferenceContext) { 4.87 MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; 4.88 4.89 ReferenceLookupHelper boundLookupHelper; 4.90 @@ -2599,7 +2656,7 @@ 4.91 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper); 4.92 4.93 //step 2 - unbound lookup 4.94 - ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(); 4.95 + ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext); 4.96 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup()); 4.97 Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper); 4.98 4.99 @@ -2739,11 +2796,11 @@ 4.100 * Returns an unbound version of this lookup helper. By default, this 4.101 * method returns an dummy lookup helper. 4.102 */ 4.103 - ReferenceLookupHelper unboundLookup() { 4.104 + ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 4.105 //dummy loopkup helper that always return 'methodNotFound' 4.106 return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) { 4.107 @Override 4.108 - ReferenceLookupHelper unboundLookup() { 4.109 + ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 4.110 return this; 4.111 } 4.112 @Override 4.113 @@ -2793,14 +2850,15 @@ 4.114 } 4.115 4.116 @Override 4.117 - ReferenceLookupHelper unboundLookup() { 4.118 + ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 4.119 if (TreeInfo.isStaticSelector(referenceTree.expr, names) && 4.120 argtypes.nonEmpty() && 4.121 - (argtypes.head.hasTag(NONE) || types.isSubtypeUnchecked(argtypes.head, site))) { 4.122 + (argtypes.head.hasTag(NONE) || 4.123 + types.isSubtypeUnchecked(inferenceContext.asFree(argtypes.head), site))) { 4.124 return new UnboundMethodReferenceLookupHelper(referenceTree, name, 4.125 site, argtypes, typeargtypes, maxPhase); 4.126 } else { 4.127 - return super.unboundLookup(); 4.128 + return super.unboundLookup(inferenceContext); 4.129 } 4.130 } 4.131 4.132 @@ -2836,7 +2894,7 @@ 4.133 } 4.134 4.135 @Override 4.136 - ReferenceLookupHelper unboundLookup() { 4.137 + ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { 4.138 return this; 4.139 } 4.140
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/lambda/MethodReference68.java Wed Jul 17 14:09:46 2013 +0100 5.3 @@ -0,0 +1,23 @@ 5.4 +/* 5.5 + * @test /nodynamiccopyright/ 5.6 + * @bug 8016175 5.7 + * @summary Add bottom-up type-checking support for unambiguous method references 5.8 + * @compile/fail/ref=MethodReference68.out -XDrawDiagnostics MethodReference68.java 5.9 + */ 5.10 +class MethodReference68 { 5.11 + interface F<X> { 5.12 + String m(X x); 5.13 + } 5.14 + 5.15 + static class Foo { 5.16 + String getName() { return ""; } 5.17 + } 5.18 + 5.19 + @SuppressWarnings("unchecked") 5.20 + <Z> void g(F<Z> fz, Z... zs) { } 5.21 + 5.22 + void test() { 5.23 + g(Foo::getName); 5.24 + g(Foo::getName, 1); //incompatible constraints, Z <: Foo, Z :> Integer 5.25 + } 5.26 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/lambda/MethodReference68.out Wed Jul 17 14:09:46 2013 +0100 6.3 @@ -0,0 +1,2 @@ 6.4 +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) 6.5 +1 error
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/tools/javac/lambda/MethodReference69.java Wed Jul 17 14:09:46 2013 +0100 7.3 @@ -0,0 +1,21 @@ 7.4 +/* 7.5 + * @test /nodynamiccopyright/ 7.6 + * @bug 8016175 7.7 + * @summary Add bottom-up type-checking support for unambiguous method references 7.8 + * @compile/fail/ref=MethodReference69.out -XDrawDiagnostics MethodReference69.java 7.9 + */ 7.10 +class MethodReference69 { 7.11 + interface F<X> { 7.12 + String m(Integer x1, X x2); 7.13 + } 7.14 + 7.15 + static class Foo { 7.16 + String getNameAt(Integer i) { return ""; } 7.17 + } 7.18 + 7.19 + <Z> void g(F<Z> fz) { } 7.20 + 7.21 + void test() { 7.22 + g(Foo::getName); 7.23 + } 7.24 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/tools/javac/lambda/MethodReference69.out Wed Jul 17 14:09:46 2013 +0100 8.3 @@ -0,0 +1,2 @@ 8.4 +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)) 8.5 +1 error
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/tools/javac/lambda/MethodReference70.java Wed Jul 17 14:09:46 2013 +0100 9.3 @@ -0,0 +1,28 @@ 9.4 +/* 9.5 + * @test /nodynamiccopyright/ 9.6 + * @bug 8016175 9.7 + * @summary Add bottom-up type-checking support for unambiguous method references 9.8 + * @compile/fail/ref=MethodReference70.out -XDrawDiagnostics MethodReference70.java 9.9 + */ 9.10 +class MethodReference70 { 9.11 + interface F<X> { 9.12 + void m(X x); 9.13 + } 9.14 + 9.15 + interface G<X> { 9.16 + Integer m(X x); 9.17 + } 9.18 + 9.19 + void m1(Integer i) { } 9.20 + 9.21 + void m2(Integer i) { } 9.22 + void m2(String i) { } 9.23 + 9.24 + <Z> void g(F<Z> fz) { } 9.25 + <Z> void g(G<Z> gz) { } 9.26 + 9.27 + void test() { 9.28 + g(this::m1); //ok 9.29 + g(this::m2); //ambiguous (stuck!) 9.30 + } 9.31 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/tools/javac/lambda/MethodReference70.out Wed Jul 17 14:09:46 2013 +0100 10.3 @@ -0,0 +1,3 @@ 10.4 +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 10.5 +MethodReference70.java:26:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z) 10.6 +2 errors
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/test/tools/javac/lambda/MethodReference71.java Wed Jul 17 14:09:46 2013 +0100 11.3 @@ -0,0 +1,26 @@ 11.4 +/* 11.5 + * @test /nodynamiccopyright/ 11.6 + * @bug 8016175 11.7 + * @summary Add bottom-up type-checking support for unambiguous method references 11.8 + * @compile/fail/ref=MethodReference71.out -XDrawDiagnostics MethodReference71.java 11.9 + */ 11.10 +class MethodReference71 { 11.11 + interface F<X> { 11.12 + void m(X x); 11.13 + } 11.14 + 11.15 + interface G<X> { 11.16 + Integer m(X x); 11.17 + } 11.18 + 11.19 + void m1(Integer i) { } 11.20 + void m2(Integer... i) { } 11.21 + 11.22 + <Z> void g(F<Z> f) { } 11.23 + <Z> void g(G<Z> g) { } 11.24 + 11.25 + void test() { 11.26 + g(this::m1); //ok 11.27 + g(this::m2); //ambiguous (stuck!) 11.28 + } 11.29 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/test/tools/javac/lambda/MethodReference71.out Wed Jul 17 14:09:46 2013 +0100 12.3 @@ -0,0 +1,3 @@ 12.4 +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 12.5 +MethodReference71.java:24:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z) 12.6 +2 errors
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/test/tools/javac/lambda/MethodReference72.java Wed Jul 17 14:09:46 2013 +0100 13.3 @@ -0,0 +1,20 @@ 13.4 +/* 13.5 + * @test /nodynamiccopyright/ 13.6 + * @bug 8016175 13.7 + * @summary Add bottom-up type-checking support for unambiguous method references 13.8 + * @compile/fail/ref=MethodReference72.out -XDrawDiagnostics MethodReference72.java 13.9 + */ 13.10 +class MethodReference72 { 13.11 + interface F<X> { 13.12 + @SuppressWarnings("unchecked") 13.13 + void m(X... x); 13.14 + } 13.15 + 13.16 + void m1(Integer i) { } 13.17 + 13.18 + <Z> void g(F<Z> f) { } 13.19 + 13.20 + void test() { 13.21 + g(this::m1); //? 13.22 + } 13.23 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/test/tools/javac/lambda/MethodReference72.out Wed Jul 17 14:09:46 2013 +0100 14.3 @@ -0,0 +1,2 @@ 14.4 +MethodReference72.java:18:9: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference72.F<Z>, @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))))) 14.5 +1 error
15.1 --- a/test/tools/javac/lambda/TargetType60.out Wed Jul 17 14:04:01 2013 +0100 15.2 +++ b/test/tools/javac/lambda/TargetType60.out Wed Jul 17 14:09:46 2013 +0100 15.3 @@ -1,7 +1,7 @@ 15.4 TargetType60.java:54:21: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType60.Sam0), TargetType60, kindname.method, <U>g(TargetType60.Sam1<U>), TargetType60 15.5 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 15.6 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 15.7 -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))))) 15.8 +TargetType60.java:60:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n1(java.lang.String)) 15.9 TargetType60.java:61:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n2(TargetType60,java.lang.String)) 15.10 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 15.11 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
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/test/tools/javac/lambda/TargetType76.java Wed Jul 17 14:09:46 2013 +0100 16.3 @@ -0,0 +1,65 @@ 16.4 +/* 16.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 16.7 + * 16.8 + * This code is free software; you can redistribute it and/or modify it 16.9 + * under the terms of the GNU General Public License version 2 only, as 16.10 + * published by the Free Software Foundation. 16.11 + * 16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16.15 + * version 2 for more details (a copy is included in the LICENSE file that 16.16 + * accompanied this code). 16.17 + * 16.18 + * You should have received a copy of the GNU General Public License version 16.19 + * 2 along with this work; if not, write to the Free Software Foundation, 16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 16.21 + * 16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 16.23 + * or visit www.oracle.com if you need additional information or have any 16.24 + * questions. 16.25 + */ 16.26 + 16.27 +/* 16.28 + * @test 16.29 + * @bug 8016175 16.30 + * @summary Add bottom-up type-checking support for unambiguous method references 16.31 + * @compile TargetType76.java 16.32 + */ 16.33 +class TargetType76 { 16.34 + 16.35 + interface Function<X, Y> { 16.36 + Y m(X x); 16.37 + } 16.38 + 16.39 + interface OfRef<T> { } 16.40 + 16.41 + interface Supplier<X> { 16.42 + X make(); 16.43 + } 16.44 + 16.45 + interface Stream<X> { } 16.46 + 16.47 + interface Node<E> { 16.48 + Spliterator<E> spliterator(); 16.49 + } 16.50 + 16.51 + interface Spliterator<X> { 16.52 + Spliterator<X> spliterator(); 16.53 + } 16.54 + 16.55 + class RefTestData<T, I> implements OfRef<T> { 16.56 + RefTestData(I state, 16.57 + Function<I, Stream<T>> streamFn, 16.58 + Function<I, Spliterator<T>> splitrFn) { } 16.59 + } 16.60 + 16.61 + <O> OfRef<O> ofCollection(Node<O> collection) { 16.62 + return new RefTestData<>(collection, 16.63 + x->stream(x::spliterator), 16.64 + Node::spliterator); 16.65 + } 16.66 + 16.67 + <S> Stream<S> stream(Supplier<? extends Spliterator<S>> supplier) { return null; } 16.68 +}