8016175: Add bottom-up type-checking support for unambiguous method references

Type-checking of non-overloaded method references should be independent from target-type

Reviewed-by: jjg, vromero
This commit is contained in:
Maurizio Cimadamore 2013-07-17 14:09:46 +01:00
parent 941752ea25
commit 99b0413d48
16 changed files with 360 additions and 83 deletions

View file

@ -2708,10 +2708,21 @@ public class Attr extends JCTree.Visitor {
setFunctionalInfo(that, pt(), desc, target, resultInfo.checkContext.inferenceContext());
List<Type> argtypes = desc.getParameterTypes();
Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck;
Pair<Symbol, Resolve.ReferenceLookupHelper> refResult =
rs.resolveMemberReference(that.pos(), localEnv, that,
that.expr.type, that.name, argtypes, typeargtypes, true, rs.resolveMethodCheck);
if (resultInfo.checkContext.inferenceContext().free(argtypes)) {
referenceCheck = rs.new MethodReferenceCheck(resultInfo.checkContext.inferenceContext());
}
Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = null;
List<Type> 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 @@ public class Attr extends JCTree.Visitor {
}
}
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()));

View file

@ -34,15 +34,14 @@ import com.sun.tools.javac.code.Type.*;
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 @@ public class DeferredAttr extends JCTree.Visitor {
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 */
@ -479,12 +489,10 @@ public class DeferredAttr extends JCTree.Visitor {
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());
dt.tree.accept(this);
dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase);
return Type.noType;
@ -533,18 +541,7 @@ public class DeferredAttr extends JCTree.Visitor {
} 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:
@ -560,17 +557,7 @@ public class DeferredAttr extends JCTree.Visitor {
}
/** 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
@ -668,12 +655,12 @@ public class DeferredAttr extends JCTree.Visitor {
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);
}
@ -753,11 +740,13 @@ public class DeferredAttr extends JCTree.Visitor {
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;
}
@ -791,18 +780,41 @@ public class DeferredAttr extends JCTree.Visitor {
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,
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 @@ public class DeferredAttr extends JCTree.Visitor {
site = site.getUpperBound();
}
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 ?

View file

@ -149,7 +149,7 @@ public class Infer {
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 @@ public class Infer {
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;
}
//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;
}
}
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;
} else {
return to;
}
//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;
}
}
/**
* Infer cyclic inference variables as described in 15.12.2.8.
@ -1337,9 +1337,6 @@ public class Infer {
/** list of inference vars in this context */
List<Type> inferencevars;
/** backed up inference variables */
List<Type> saved_undet;
java.util.Map<FreeTypeListener, List<Type>> freeTypeListeners =
new java.util.HashMap<FreeTypeListener, List<Type>>();

View file

@ -584,6 +584,13 @@ public class Resolve {
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 @@ public class Resolve {
}
};
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,
* a list of formal types F, determines whether the types in A are
@ -850,6 +865,47 @@ public class Resolve {
}
};
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<Type> 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 @@ public class Resolve {
Name name, List<Type> argtypes,
List<Type> typeargtypes,
boolean boxingAllowed,
MethodCheck methodCheck) {
MethodCheck methodCheck,
InferenceContext inferenceContext) {
MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
ReferenceLookupHelper boundLookupHelper;
@ -2599,7 +2656,7 @@ public class Resolve {
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<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper);
@ -2739,11 +2796,11 @@ public class Resolve {
* 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 @@ public class Resolve {
}
@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 @@ public class Resolve {
}
@Override
ReferenceLookupHelper unboundLookup() {
ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) {
return this;
}

View file

@ -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
}
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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!)
}
}

View file

@ -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

View file

@ -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!)
}
}

View file

@ -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

View file

@ -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<X> {
@SuppressWarnings("unchecked")
void m(X... x);
}
void m1(Integer i) { }
<Z> void g(F<Z> f) { }
void test() {
g(this::m1); //?
}
}

View file

@ -0,0 +1,2 @@
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)))))
1 error

View file

@ -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

View file

@ -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<X, Y> {
Y m(X x);
}
interface OfRef<T> { }
interface Supplier<X> {
X make();
}
interface Stream<X> { }
interface Node<E> {
Spliterator<E> spliterator();
}
interface Spliterator<X> {
Spliterator<X> spliterator();
}
class RefTestData<T, I> implements OfRef<T> {
RefTestData(I state,
Function<I, Stream<T>> streamFn,
Function<I, Spliterator<T>> splitrFn) { }
}
<O> OfRef<O> ofCollection(Node<O> collection) {
return new RefTestData<>(collection,
x->stream(x::spliterator),
Node::spliterator);
}
<S> Stream<S> stream(Supplier<? extends Spliterator<S>> supplier) { return null; }
}