8016177: structural most specific and stuckness

Reviewed-by: jjg, vromero
This commit is contained in:
Maurizio Cimadamore 2013-09-02 22:38:36 +01:00 committed by Vicente Romero
parent 4337286502
commit 0382c78ff1
76 changed files with 1377 additions and 668 deletions

View file

@ -266,6 +266,11 @@ public class Flags {
*/
public static final long THROWS = 1L<<47;
/**
* Flag that marks potentially ambiguous overloads
*/
public static final long POTENTIALLY_AMBIGUOUS = 1L<<48;
/** Modifier masks.
*/
public static final int

View file

@ -174,6 +174,11 @@ public class Lint
*/
OPTIONS("options"),
/**
* Warn about issues regarding method overloads.
*/
OVERLOADS("overloads"),
/**
* Warn about issues regarding method overrides.
*/

View file

@ -3055,7 +3055,7 @@ public class Types {
/**
* Does t have the same bounds for quantified variables as s?
*/
boolean hasSameBounds(ForAll t, ForAll s) {
public boolean hasSameBounds(ForAll t, ForAll s) {
List<Type> l1 = t.tvars;
List<Type> l2 = s.tvars;
while (l1.nonEmpty() && l2.nonEmpty() &&

View file

@ -2396,8 +2396,6 @@ public class Attr extends JCTree.Visitor {
new ResultInfo(VAL, lambdaType.getReturnType(), funcContext);
localEnv.info.returnResult = bodyResultInfo;
Log.DeferredDiagnosticHandler lambdaDeferredHandler = new Log.DeferredDiagnosticHandler(log);
try {
if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
attribTree(that.getBody(), localEnv, bodyResultInfo);
} else {
@ -2405,28 +2403,6 @@ public class Attr extends JCTree.Visitor {
attribStats(body.stats, localEnv);
}
if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE) {
//check for errors in lambda body
for (JCDiagnostic deferredDiag : lambdaDeferredHandler.getDiagnostics()) {
if (deferredDiag.getKind() == JCDiagnostic.Kind.ERROR) {
resultInfo.checkContext
.report(that, diags.fragment("bad.arg.types.in.lambda", TreeInfo.types(that.params),
deferredDiag)); //hidden diag parameter
//we mark the lambda as erroneous - this is crucial in the recovery step
//as parameter-dependent type error won't be reported in that stage,
//meaning that a lambda will be deemed erroeneous only if there is
//a target-independent error (which will cause method diagnostic
//to be skipped).
result = that.type = types.createErrorType(target);
return;
}
}
}
} finally {
lambdaDeferredHandler.reportDeferredDiagnostics();
log.popDiagnosticHandler(lambdaDeferredHandler);
}
result = check(that, target, VAL, resultInfo);
boolean isSpeculativeRound =
@ -3731,7 +3707,7 @@ public class Attr extends JCTree.Visitor {
* Check that method arguments conform to its instantiation.
**/
public Type checkMethod(Type site,
Symbol sym,
final Symbol sym,
ResultInfo resultInfo,
Env<AttrContext> env,
final List<JCExpression> argtrees,
@ -3820,8 +3796,19 @@ public class Attr extends JCTree.Visitor {
resultInfo.checkContext.report(env.tree.pos(), ex.getDiagnostic());
return types.createErrorType(site);
} catch (Resolve.InapplicableMethodException ex) {
Assert.error(ex.getDiagnostic().getMessage(Locale.getDefault()));
return null;
final JCDiagnostic diag = ex.getDiagnostic();
Resolve.InapplicableSymbolError errSym = rs.new InapplicableSymbolError(null) {
@Override
protected Pair<Symbol, JCDiagnostic> errCandidate() {
return new Pair<Symbol, JCDiagnostic>(sym, diag);
}
};
List<Type> argtypes2 = Type.map(argtypes,
rs.new ResolveDeferredRecoveryMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase));
JCDiagnostic errDiag = errSym.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR,
env.tree, sym, site, sym.name, argtypes2, typeargtypes);
log.report(errDiag);
return types.createErrorType(site);
}
}

View file

@ -2368,7 +2368,10 @@ public class Check {
//for each method m1 that is overridden (directly or indirectly)
//by method 'sym' in 'site'...
for (Symbol m1 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
if (!sym.overrides(m1, site.tsym, types, false)) continue;
if (!sym.overrides(m1, site.tsym, types, false)) {
checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)m1);
continue;
}
//...check each method m2 that is a member of 'site'
for (Symbol m2 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
if (m2 == m1) continue;
@ -2406,13 +2409,16 @@ public class Check {
for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
//if (i) the signature of 'sym' is not a subsignature of m1 (seen as
//a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck) &&
types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) {
if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
log.error(pos,
"name.clash.same.erasure.no.hide",
sym, sym.location(),
s, s.location());
return;
} else {
checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)s);
}
}
}
}
@ -2496,6 +2502,62 @@ public class Check {
}
}
/**
* Report warnings for potentially ambiguous method declarations. Two declarations
* are potentially ambiguous if they feature two unrelated functional interface
* in same argument position (in which case, a call site passing an implicit
* lambda would be ambiguous).
*/
void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site,
MethodSymbol msym1, MethodSymbol msym2) {
if (msym1 != msym2 &&
allowDefaultMethods &&
lint.isEnabled(LintCategory.OVERLOADS) &&
(msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 &&
(msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) {
Type mt1 = types.memberType(site, msym1);
Type mt2 = types.memberType(site, msym2);
//if both generic methods, adjust type variables
if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) &&
types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) {
mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars);
}
//expand varargs methods if needed
int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length());
List<Type> args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true);
List<Type> args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true);
//if arities don't match, exit
if (args1.length() != args2.length()) return;
boolean potentiallyAmbiguous = false;
while (args1.nonEmpty() && args2.nonEmpty()) {
Type s = args1.head;
Type t = args2.head;
if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) {
if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) &&
types.findDescriptorType(s).getParameterTypes().length() > 0 &&
types.findDescriptorType(s).getParameterTypes().length() ==
types.findDescriptorType(t).getParameterTypes().length()) {
potentiallyAmbiguous = true;
} else {
break;
}
}
args1 = args1.tail;
args2 = args2.tail;
}
if (potentiallyAmbiguous) {
//we found two incompatible functional interfaces with same arity
//this means a call site passing an implicit lambda would be ambigiuous
msym1.flags_field |= POTENTIALLY_AMBIGUOUS;
msym2.flags_field |= POTENTIALLY_AMBIGUOUS;
log.warning(LintCategory.OVERLOADS, pos, "potentially.ambiguous.overload",
msym1, msym1.location(),
msym2, msym2.location());
return;
}
}
}
/** Report a conflict between a user symbol and a synthetic symbol.
*/
private void syntheticError(DiagnosticPosition pos, Symbol sym) {

View file

@ -25,6 +25,7 @@
package com.sun.tools.javac.comp;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
@ -39,7 +40,9 @@ import com.sun.tools.javac.tree.JCTree.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
@ -98,7 +101,7 @@ public class DeferredAttr extends JCTree.Visitor {
emptyDeferredAttrContext =
new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
@Override
void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
void addDeferredAttrNode(DeferredType dt, ResultInfo ri, DeferredStuckPolicy deferredStuckPolicy) {
Assert.error("Empty deferred context!");
}
@Override
@ -149,15 +152,15 @@ public class DeferredAttr extends JCTree.Visitor {
class Entry {
JCTree speculativeTree;
Resolve.MethodResolutionPhase phase;
ResultInfo resultInfo;
public Entry(JCTree speculativeTree, MethodResolutionPhase phase) {
public Entry(JCTree speculativeTree, ResultInfo resultInfo) {
this.speculativeTree = speculativeTree;
this.phase = phase;
this.resultInfo = resultInfo;
}
boolean matches(Resolve.MethodResolutionPhase phase) {
return this.phase == phase;
boolean matches(MethodResolutionPhase phase) {
return resultInfo.checkContext.deferredAttrContext().phase == phase;
}
}
@ -178,12 +181,13 @@ public class DeferredAttr extends JCTree.Visitor {
* Stores a speculative cache entry corresponding to given symbol
* and resolution phase
*/
void put(Symbol msym, JCTree speculativeTree, MethodResolutionPhase phase) {
void put(JCTree speculativeTree, ResultInfo resultInfo) {
Symbol msym = resultInfo.checkContext.deferredAttrContext().msym;
List<Entry> entries = cache.get(msym);
if (entries == null) {
entries = List.nil();
}
cache.put(msym, entries.prepend(new Entry(speculativeTree, phase)));
cache.put(msym, entries.prepend(new Entry(speculativeTree, resultInfo)));
}
}
@ -203,15 +207,24 @@ public class DeferredAttr extends JCTree.Visitor {
* attribution round must follow one or more speculative rounds.
*/
Type check(ResultInfo resultInfo) {
return check(resultInfo, stuckVars(tree, env, resultInfo), basicCompleter);
DeferredStuckPolicy deferredStuckPolicy;
if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
deferredStuckPolicy = dummyStuckPolicy;
} else if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE) {
deferredStuckPolicy = new OverloadStuckPolicy(resultInfo, this);
} else {
deferredStuckPolicy = new CheckStuckPolicy(resultInfo, this);
}
return check(resultInfo, deferredStuckPolicy, basicCompleter);
}
Type check(ResultInfo resultInfo, List<Type> stuckVars, DeferredTypeCompleter deferredTypeCompleter) {
private Type check(ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy,
DeferredTypeCompleter deferredTypeCompleter) {
DeferredAttrContext deferredAttrContext =
resultInfo.checkContext.deferredAttrContext();
Assert.check(deferredAttrContext != emptyDeferredAttrContext);
if (stuckVars.nonEmpty()) {
deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars);
if (deferredStuckPolicy.isStuck()) {
deferredAttrContext.addDeferredAttrNode(this, resultInfo, deferredStuckPolicy);
return Type.noType;
} else {
try {
@ -236,6 +249,7 @@ public class DeferredAttr extends JCTree.Visitor {
Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext);
}
/**
* A basic completer for deferred types. This completer type-checks a deferred type
* using attribution; depending on the attribution mode, this could be either standard
@ -249,7 +263,7 @@ public class DeferredAttr extends JCTree.Visitor {
//speculative rounds...
Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE);
JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
dt.speculativeCache.put(speculativeTree, resultInfo);
return speculativeTree.type;
case CHECK:
Assert.check(dt.mode != null);
@ -267,6 +281,45 @@ public class DeferredAttr extends JCTree.Visitor {
}
};
/**
* Policy for detecting stuck expressions. Different criteria might cause
* an expression to be judged as stuck, depending on whether the check
* is performed during overload resolution or after most specific.
*/
interface DeferredStuckPolicy {
/**
* Has the policy detected that a given expression should be considered stuck?
*/
boolean isStuck();
/**
* Get the set of inference variables a given expression depends upon.
*/
Set<Type> stuckVars();
/**
* Get the set of inference variables which might get new constraints
* if a given expression is being type-checked.
*/
Set<Type> depVars();
}
/**
* Basic stuck policy; an expression is never considered to be stuck.
*/
DeferredStuckPolicy dummyStuckPolicy = new DeferredStuckPolicy() {
@Override
public boolean isStuck() {
return false;
}
@Override
public Set<Type> stuckVars() {
return Collections.emptySet();
}
@Override
public Set<Type> depVars() {
return Collections.emptySet();
}
};
/**
* The 'mode' in which the deferred type is to be type-checked
*/
@ -388,8 +441,9 @@ public class DeferredAttr extends JCTree.Visitor {
* Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable
* Nodes added this way act as 'roots' for the out-of-order method checking process.
*/
void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, stuckVars));
void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo,
DeferredStuckPolicy deferredStuckPolicy) {
deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, deferredStuckPolicy));
}
/**
@ -400,23 +454,52 @@ public class DeferredAttr extends JCTree.Visitor {
*/
void complete() {
while (!deferredAttrNodes.isEmpty()) {
Set<Type> stuckVars = new LinkedHashSet<Type>();
Map<Type, Set<Type>> depVarsMap = new LinkedHashMap<Type, Set<Type>>();
List<Type> stuckVars = List.nil();
boolean progress = false;
//scan a defensive copy of the node list - this is because a deferred
//attribution round can add new nodes to the list
for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
if (!deferredAttrNode.process(this)) {
stuckVars.addAll(deferredAttrNode.stuckVars);
List<Type> restStuckVars =
List.from(deferredAttrNode.deferredStuckPolicy.stuckVars())
.intersect(inferenceContext.restvars());
stuckVars = stuckVars.prependList(restStuckVars);
//update dependency map
for (Type t : List.from(deferredAttrNode.deferredStuckPolicy.depVars())
.intersect(inferenceContext.restvars())) {
Set<Type> prevDeps = depVarsMap.get(t);
if (prevDeps == null) {
prevDeps = new LinkedHashSet<Type>();
depVarsMap.put(t, prevDeps);
}
prevDeps.addAll(restStuckVars);
}
} else {
deferredAttrNodes.remove(deferredAttrNode);
progress = true;
}
}
if (!progress) {
DeferredAttrContext dac = this;
while (dac != emptyDeferredAttrContext) {
if (dac.mode == AttrMode.SPECULATIVE) {
//unsticking does not take place during overload
break;
}
dac = dac.parent;
}
//remove all variables that have already been instantiated
//from the list of stuck variables
inferenceContext.solveAny(List.from(stuckVars), warn);
try {
inferenceContext.solveAny(stuckVars, depVarsMap, warn);
inferenceContext.notifyChange();
} catch (Infer.GraphStrategy.NodeNotFoundException ex) {
//this means that we are in speculative mode and the
//set of contraints are too tight for progess to be made.
//Just leave the remaining expressions as stuck.
break;
}
}
}
}
@ -426,7 +509,7 @@ public class DeferredAttr extends JCTree.Visitor {
* Class representing a deferred attribution node. It keeps track of
* a deferred type, along with the expected target type information.
*/
class DeferredAttrNode implements Infer.FreeTypeListener {
class DeferredAttrNode {
/** underlying deferred type */
DeferredType dt;
@ -434,22 +517,13 @@ public class DeferredAttr extends JCTree.Visitor {
/** underlying target type information */
ResultInfo resultInfo;
/** list of uninferred inference variables causing this node to be stuck */
List<Type> stuckVars;
/** stuck policy associated with this node */
DeferredStuckPolicy deferredStuckPolicy;
DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy) {
this.dt = dt;
this.resultInfo = resultInfo;
this.stuckVars = stuckVars;
if (!stuckVars.isEmpty()) {
resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
}
}
@Override
public void typesInferred(InferenceContext inferenceContext) {
stuckVars = List.nil();
resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
this.deferredStuckPolicy = deferredStuckPolicy;
}
/**
@ -457,24 +531,41 @@ public class DeferredAttr extends JCTree.Visitor {
* Invariant: a stuck node cannot be processed.
*/
@SuppressWarnings("fallthrough")
boolean process(DeferredAttrContext deferredAttrContext) {
boolean process(final DeferredAttrContext deferredAttrContext) {
switch (deferredAttrContext.mode) {
case SPECULATIVE:
dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
if (deferredStuckPolicy.isStuck()) {
dt.check(resultInfo, dummyStuckPolicy, new StructuralStuckChecker());
return true;
} else {
Assert.error("Cannot get here");
}
case CHECK:
if (stuckVars.nonEmpty()) {
if (deferredStuckPolicy.isStuck()) {
//stuck expression - see if we can propagate
if (deferredAttrContext.parent != emptyDeferredAttrContext &&
Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, List.from(stuckVars))) {
deferredAttrContext.parent.deferredAttrNodes.add(this);
dt.check(resultInfo, List.<Type>nil(), dummyCompleter);
Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars,
List.from(deferredStuckPolicy.stuckVars()))) {
deferredAttrContext.parent.addDeferredAttrNode(dt,
resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
@Override
public InferenceContext inferenceContext() {
return deferredAttrContext.parent.inferenceContext;
}
@Override
public DeferredAttrContext deferredAttrContext() {
return deferredAttrContext.parent;
}
}), deferredStuckPolicy);
dt.tree.type = Type.stuckType;
return true;
} else {
return false;
}
} else {
dt.check(resultInfo, stuckVars, basicCompleter);
ResultInfo instResultInfo =
resultInfo.dup(deferredAttrContext.inferenceContext.asInstType(resultInfo.pt));
dt.check(instResultInfo, dummyStuckPolicy, basicCompleter);
return true;
}
default:
@ -489,12 +580,14 @@ 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;
dt.tree.accept(this);
dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase);
dt.speculativeCache.put(stuckTree, resultInfo);
return Type.noType;
}
@ -541,15 +634,25 @@ public class DeferredAttr extends JCTree.Visitor {
} catch (Types.FunctionDescriptorLookupError ex) {
checkContext.report(null, ex.getDiagnostic());
}
switch (tree.sym.kind) {
Env<AttrContext> localEnv = env.dup(tree);
JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
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, localEnv, mref2, exprTree.type,
tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, inferenceContext);
switch (lookupRes.fst.kind) {
//note: as argtypes are erroneous types, type-errors must
//have been caused by arity mismatch
case Kinds.ABSENT_MTH:
case Kinds.WRONG_MTH:
case Kinds.WRONG_MTHS:
case Kinds.STATICERR:
case Kinds.MISSING_ENCL:
checkContext.report(null, diags.fragment("incompatible.arg.types.in.mref"));
checkContext.report(tree, diags.fragment("incompatible.arg.types.in.mref"));
}
}
}
@ -575,18 +678,12 @@ public class DeferredAttr extends JCTree.Visitor {
infer.emptyContext, emptyDeferredAttrContext, types.noWarnings);
}
protected boolean validState(DeferredType dt) {
return dt.mode != null &&
deferredAttrContext.mode.ordinal() <= dt.mode.ordinal();
}
@Override
public Type apply(Type t) {
if (!t.hasTag(DEFERRED)) {
return t.map(this);
} else {
DeferredType dt = (DeferredType)t;
Assert.check(validState(dt));
return typeOf(dt);
}
}
@ -623,11 +720,6 @@ public class DeferredAttr extends JCTree.Visitor {
recover(dt) : owntype;
}
@Override
protected boolean validState(DeferredType dt) {
return true;
}
/**
* Synthesize a type for a deferred type that hasn't been previously
* reduced to an ordinary type. Functional deferred types and conditionals
@ -646,25 +738,6 @@ public class DeferredAttr extends JCTree.Visitor {
}
}
/**
* Retrieves the list of inference variables that need to be inferred before
* an AST node can be type-checked
*/
@SuppressWarnings("fallthrough")
List<Type> stuckVars(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
return List.nil();
} else {
return stuckVarsInternal(tree, resultInfo.pt, env, resultInfo.checkContext.inferenceContext());
}
}
//where
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);
}
/**
* A special tree scanner that would only visit portions of a given tree.
* The set of nodes visited by the scanner can be customized at construction-time.
@ -737,17 +810,41 @@ public class DeferredAttr extends JCTree.Visitor {
* inferring types that make some of the nested expressions incompatible
* with their corresponding instantiated target
*/
class StuckChecker extends PolyScanner {
class CheckStuckPolicy extends PolyScanner implements DeferredStuckPolicy, Infer.FreeTypeListener {
Type pt;
Env<AttrContext> env;
Infer.InferenceContext inferenceContext;
Set<Type> stuckVars = new LinkedHashSet<Type>();
Set<Type> depVars = new LinkedHashSet<Type>();
StuckChecker(Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
this.pt = pt;
this.env = env;
this.inferenceContext = inferenceContext;
@Override
public boolean isStuck() {
return !stuckVars.isEmpty();
}
@Override
public Set<Type> stuckVars() {
return stuckVars;
}
@Override
public Set<Type> depVars() {
return depVars;
}
public CheckStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
this.pt = resultInfo.pt;
this.inferenceContext = resultInfo.checkContext.inferenceContext();
scan(dt.tree);
if (!stuckVars.isEmpty()) {
resultInfo.checkContext.inferenceContext()
.addFreeTypeListener(List.from(stuckVars), this);
}
}
@Override
public void typesInferred(InferenceContext inferenceContext) {
stuckVars.clear();
}
@Override
@ -763,6 +860,7 @@ public class DeferredAttr extends JCTree.Visitor {
if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
freeArgVars.nonEmpty()) {
stuckVars.addAll(freeArgVars);
depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
}
scanLambdaBody(tree, descType.getReturnType());
}
@ -780,41 +878,34 @@ public class DeferredAttr extends JCTree.Visitor {
Type descType = types.findDescriptorType(pt);
List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
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())) {
if (freeArgVars.nonEmpty() &&
tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) {
stuckVars.addAll(freeArgVars);
}
depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
}
}
void scanLambdaBody(JCLambda lambda, final Type pt) {
if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
stuckVars.addAll(stuckVarsInternal(lambda.body, pt, env, inferenceContext));
Type prevPt = this.pt;
try {
this.pt = pt;
scan(lambda.body);
} finally {
this.pt = prevPt;
}
} else {
LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
@Override
public void visitReturn(JCReturn tree) {
if (tree.expr != null) {
stuckVars.addAll(stuckVarsInternal(tree.expr, pt, env, inferenceContext));
Type prevPt = CheckStuckPolicy.this.pt;
try {
CheckStuckPolicy.this.pt = pt;
CheckStuckPolicy.this.scan(tree.expr);
} finally {
CheckStuckPolicy.this.pt = prevPt;
}
}
}
};
@ -823,6 +914,42 @@ public class DeferredAttr extends JCTree.Visitor {
}
}
/**
* This visitor is used to check that structural expressions conform
* to their target - this step is required as inference could end up
* inferring types that make some of the nested expressions incompatible
* with their corresponding instantiated target
*/
class OverloadStuckPolicy extends CheckStuckPolicy implements DeferredStuckPolicy {
boolean stuck;
@Override
public boolean isStuck() {
return super.isStuck() || stuck;
}
public OverloadStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
super(resultInfo, dt);
}
@Override
public void visitLambda(JCLambda tree) {
super.visitLambda(tree);
if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT) {
stuck = true;
}
}
@Override
public void visitReference(JCMemberReference tree) {
super.visitReference(tree);
if (tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) {
stuck = true;
}
}
}
/**
* Does the argument expression {@code expr} need speculative type-checking?
*/
@ -904,6 +1031,26 @@ public class DeferredAttr extends JCTree.Visitor {
@Override
public void visitReference(JCMemberReference tree) {
//perform arity-based check
Env<AttrContext> localEnv = env.dup(tree);
JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
attr.memberReferenceQualifierResult(tree));
JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
mref2.expr = exprTree;
Pair<Symbol, ReferenceLookupHelper> lookupRes =
rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
tree.name, List.<Type>nil(), null, true, rs.nilMethodCheck,
infer.emptyContext);
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())) {
tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED;
} else {
tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED;
}
//a method reference is always a poly expression
result = ArgumentExpressionKind.POLY;
}

View file

@ -40,17 +40,17 @@ import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph;
import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node;
import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import com.sun.tools.javac.util.GraphUtils.TarjanNode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import static com.sun.tools.javac.code.TypeTag.*;
@ -113,6 +113,12 @@ public class Infer {
super(diags);
}
@Override
InapplicableMethodException setMessage() {
//no message to set
return this;
}
@Override
InapplicableMethodException setMessage(JCDiagnostic diag) {
messages = messages.append(diag);
@ -1006,10 +1012,24 @@ public class Infer {
* and (ii) tell th engine when we are done fixing inference variables
*/
interface GraphStrategy {
/**
* A NodeNotFoundException is thrown whenever an inference strategy fails
* to pick the next node to solve in the inference graph.
*/
public static class NodeNotFoundException extends RuntimeException {
private static final long serialVersionUID = 0;
InferenceGraph graph;
public NodeNotFoundException(InferenceGraph graph) {
this.graph = graph;
}
}
/**
* Pick the next node (leaf) to solve in the graph
*/
Node pickNode(InferenceGraph g);
Node pickNode(InferenceGraph g) throws NodeNotFoundException;
/**
* Is this the last step?
*/
@ -1022,7 +1042,10 @@ public class Infer {
*/
abstract class LeafSolver implements GraphStrategy {
public Node pickNode(InferenceGraph g) {
Assert.check(!g.nodes.isEmpty(), "No nodes to solve!");
if (g.nodes.isEmpty()) {
//should not happen
throw new NodeNotFoundException(g);
};
return g.nodes.get(0);
}
@ -1069,6 +1092,7 @@ public class Infer {
*/
abstract class BestLeafSolver extends LeafSolver {
/** list of ivars of which at least one must be solved */
List<Type> varsToSolve;
BestLeafSolver(List<Type> varsToSolve) {
@ -1076,54 +1100,66 @@ public class Infer {
}
/**
* Computes the minimum path that goes from a given node to any of the nodes
* containing a variable in {@code varsToSolve}. For any given path, the cost
* is computed as the total number of type-variables that should be eagerly
* instantiated across that path.
* Computes a path that goes from a given node to the leafs in the graph.
* Typically this will start from a node containing a variable in
* {@code varsToSolve}. For any given path, the cost is computed as the total
* number of type-variables that should be eagerly instantiated across that path.
*/
int computeMinPath(InferenceGraph g, Node n) {
return computeMinPath(g, n, List.<Node>nil(), 0);
Pair<List<Node>, Integer> computeTreeToLeafs(Node n) {
Pair<List<Node>, Integer> cachedPath = treeCache.get(n);
if (cachedPath == null) {
//cache miss
if (n.isLeaf()) {
//if leaf, stop
cachedPath = new Pair<List<Node>, Integer>(List.of(n), n.data.length());
} else {
//if non-leaf, proceed recursively
Pair<List<Node>, Integer> path = new Pair<List<Node>, Integer>(List.of(n), n.data.length());
for (Node n2 : n.getAllDependencies()) {
if (n2 == n) continue;
Pair<List<Node>, Integer> subpath = computeTreeToLeafs(n2);
path = new Pair<List<Node>, Integer>(
path.fst.prependList(subpath.fst),
path.snd + subpath.snd);
}
cachedPath = path;
}
//save results in cache
treeCache.put(n, cachedPath);
}
return cachedPath;
}
int computeMinPath(InferenceGraph g, Node n, List<Node> path, int cost) {
if (path.contains(n)) return Integer.MAX_VALUE;
List<Node> path2 = path.prepend(n);
int cost2 = cost + n.data.size();
if (!Collections.disjoint(n.data, varsToSolve)) {
return cost2;
} else {
int bestPath = Integer.MAX_VALUE;
for (Node n2 : g.nodes) {
if (n2.deps.contains(n)) {
int res = computeMinPath(g, n2, path2, cost2);
if (res < bestPath) {
bestPath = res;
}
}
}
return bestPath;
}
}
/** cache used to avoid redundant computation of tree costs */
final Map<Node, Pair<List<Node>, Integer>> treeCache =
new HashMap<Node, Pair<List<Node>, Integer>>();
/** constant value used to mark non-existent paths */
final Pair<List<Node>, Integer> noPath =
new Pair<List<Node>, Integer>(null, Integer.MAX_VALUE);
/**
* Pick the leaf that minimize cost
*/
@Override
public Node pickNode(final InferenceGraph g) {
final Map<Node, Integer> leavesMap = new HashMap<Node, Integer>();
treeCache.clear(); //graph changes at every step - cache must be cleared
Pair<List<Node>, Integer> bestPath = noPath;
for (Node n : g.nodes) {
if (n.isLeaf(n)) {
leavesMap.put(n, computeMinPath(g, n));
if (!Collections.disjoint(n.data, varsToSolve)) {
Pair<List<Node>, Integer> path = computeTreeToLeafs(n);
//discard all paths containing at least a node in the
//closure computed above
if (path.snd < bestPath.snd) {
bestPath = path;
}
}
Assert.check(!leavesMap.isEmpty(), "No nodes to solve!");
TreeSet<Node> orderedLeaves = new TreeSet<Node>(new Comparator<Node>() {
public int compare(Node n1, Node n2) {
return leavesMap.get(n1) - leavesMap.get(n2);
}
});
orderedLeaves.addAll(leavesMap.keySet());
return orderedLeaves.first();
if (bestPath == noPath) {
//no path leads there
throw new NodeNotFoundException(g);
}
return bestPath.fst.head;
}
}
@ -1320,6 +1356,33 @@ public class Infer {
}
}
/**
* There are two kinds of dependencies between inference variables. The basic
* kind of dependency (or bound dependency) arises when a variable mention
* another variable in one of its bounds. There's also a more subtle kind
* of dependency that arises when a variable 'might' lead to better constraints
* on another variable (this is typically the case with variables holding up
* stuck expressions).
*/
enum DependencyKind implements GraphUtils.DependencyKind {
/** bound dependency */
BOUND("dotted"),
/** stuck dependency */
STUCK("dashed");
final String dotSyle;
private DependencyKind(String dotSyle) {
this.dotSyle = dotSyle;
}
@Override
public String getDotStyle() {
return dotSyle;
}
}
/**
* This is the graph inference solver - the solver organizes all inference variables in
* a given inference context by bound dependencies - in the general case, such dependencies
@ -1331,10 +1394,12 @@ public class Infer {
class GraphSolver {
InferenceContext inferenceContext;
Map<Type, Set<Type>> stuckDeps;
Warner warn;
GraphSolver(InferenceContext inferenceContext, Warner warn) {
GraphSolver(InferenceContext inferenceContext, Map<Type, Set<Type>> stuckDeps, Warner warn) {
this.inferenceContext = inferenceContext;
this.stuckDeps = stuckDeps;
this.warn = warn;
}
@ -1345,7 +1410,7 @@ public class Infer {
*/
void solve(GraphStrategy sstrategy) {
checkWithinBounds(inferenceContext, warn); //initial propagation of bounds
InferenceGraph inferenceGraph = new InferenceGraph();
InferenceGraph inferenceGraph = new InferenceGraph(stuckDeps);
while (!sstrategy.done()) {
InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph);
List<Type> varsToSolve = List.from(nodeToSolve.data);
@ -1390,20 +1455,23 @@ public class Infer {
*/
class Node extends GraphUtils.TarjanNode<ListBuffer<Type>> {
Set<Node> deps;
/** map listing all dependencies (grouped by kind) */
EnumMap<DependencyKind, Set<Node>> deps;
Node(Type ivar) {
super(ListBuffer.of(ivar));
this.deps = new HashSet<Node>();
this.deps = new EnumMap<DependencyKind, Set<Node>>(DependencyKind.class);
}
@Override
public Iterable<? extends Node> getDependencies() {
return deps;
public GraphUtils.DependencyKind[] getSupportedDependencyKinds() {
return DependencyKind.values();
}
@Override
public String printDependency(GraphUtils.Node<ListBuffer<Type>> to) {
public String getDependencyName(GraphUtils.Node<ListBuffer<Type>> to, GraphUtils.DependencyKind dk) {
if (dk == DependencyKind.STUCK) return "";
else {
StringBuilder buf = new StringBuilder();
String sep = "";
for (Type from : data) {
@ -1418,36 +1486,141 @@ public class Infer {
}
return buf.toString();
}
boolean isLeaf(Node n) {
//no deps, or only one self dep
return (n.deps.isEmpty() ||
n.deps.size() == 1 && n.deps.contains(n));
}
void mergeWith(List<? extends Node> nodes) {
@Override
public Iterable<? extends Node> getAllDependencies() {
return getDependencies(DependencyKind.values());
}
@Override
public Iterable<? extends TarjanNode<ListBuffer<Type>>> getDependenciesByKind(GraphUtils.DependencyKind dk) {
return getDependencies((DependencyKind)dk);
}
/**
* Retrieves all dependencies with given kind(s).
*/
protected Set<Node> getDependencies(DependencyKind... depKinds) {
Set<Node> buf = new LinkedHashSet<Node>();
for (DependencyKind dk : depKinds) {
Set<Node> depsByKind = deps.get(dk);
if (depsByKind != null) {
buf.addAll(depsByKind);
}
}
return buf;
}
/**
* Adds dependency with given kind.
*/
protected void addDependency(DependencyKind dk, Node depToAdd) {
Set<Node> depsByKind = deps.get(dk);
if (depsByKind == null) {
depsByKind = new LinkedHashSet<Node>();
deps.put(dk, depsByKind);
}
depsByKind.add(depToAdd);
}
/**
* Add multiple dependencies of same given kind.
*/
protected void addDependencies(DependencyKind dk, Set<Node> depsToAdd) {
for (Node n : depsToAdd) {
addDependency(dk, n);
}
}
/**
* Remove a dependency, regardless of its kind.
*/
protected Set<DependencyKind> removeDependency(Node n) {
Set<DependencyKind> removedKinds = new HashSet<>();
for (DependencyKind dk : DependencyKind.values()) {
Set<Node> depsByKind = deps.get(dk);
if (depsByKind == null) continue;
if (depsByKind.remove(n)) {
removedKinds.add(dk);
}
}
return removedKinds;
}
/**
* Compute closure of a give node, by recursively walking
* through all its dependencies (of given kinds)
*/
protected Set<Node> closure(DependencyKind... depKinds) {
boolean progress = true;
Set<Node> closure = new HashSet<Node>();
closure.add(this);
while (progress) {
progress = false;
for (Node n1 : new HashSet<Node>(closure)) {
progress = closure.addAll(n1.getDependencies(depKinds));
}
}
return closure;
}
/**
* Is this node a leaf? This means either the node has no dependencies,
* or it just has self-dependencies.
*/
protected boolean isLeaf() {
//no deps, or only one self dep
Set<Node> allDeps = getDependencies(DependencyKind.BOUND, DependencyKind.STUCK);
if (allDeps.isEmpty()) return true;
for (Node n : allDeps) {
if (n != this) {
return false;
}
}
return true;
}
/**
* Merge this node with another node, acquiring its dependencies.
* This routine is used to merge all cyclic node together and
* form an acyclic graph.
*/
protected void mergeWith(List<? extends Node> nodes) {
for (Node n : nodes) {
Assert.check(n.data.length() == 1, "Attempt to merge a compound node!");
data.appendList(n.data);
deps.addAll(n.deps);
for (DependencyKind dk : DependencyKind.values()) {
addDependencies(dk, n.getDependencies(dk));
}
}
//update deps
Set<Node> deps2 = new HashSet<Node>();
for (Node d : deps) {
EnumMap<DependencyKind, Set<Node>> deps2 = new EnumMap<DependencyKind, Set<Node>>(DependencyKind.class);
for (DependencyKind dk : DependencyKind.values()) {
for (Node d : getDependencies(dk)) {
Set<Node> depsByKind = deps2.get(dk);
if (depsByKind == null) {
depsByKind = new LinkedHashSet<Node>();
deps2.put(dk, depsByKind);
}
if (data.contains(d.data.first())) {
deps2.add(this);
depsByKind.add(this);
} else {
deps2.add(d);
depsByKind.add(d);
}
}
}
deps = deps2;
}
void graphChanged(Node from, Node to) {
if (deps.contains(from)) {
deps.remove(from);
/**
* Notify all nodes that something has changed in the graph
* topology.
*/
private void graphChanged(Node from, Node to) {
for (DependencyKind dk : removeDependency(from)) {
if (to != null) {
deps.add(to);
addDependency(dk, to);
}
}
}
@ -1456,8 +1629,21 @@ public class Infer {
/** the nodes in the inference graph */
ArrayList<Node> nodes;
InferenceGraph() {
initNodes();
InferenceGraph(Map<Type, Set<Type>> optDeps) {
initNodes(optDeps);
}
/**
* Basic lookup helper for retrieving a graph node given an inference
* variable type.
*/
public Node findNode(Type t) {
for (Node n : nodes) {
if (n.data.contains(t)) {
return n;
}
}
return null;
}
/**
@ -1486,22 +1672,30 @@ public class Infer {
* in the graph. For each component containing more than one node, a super node is
* created, effectively replacing the original cyclic nodes.
*/
void initNodes() {
void initNodes(Map<Type, Set<Type>> stuckDeps) {
//add nodes
nodes = new ArrayList<Node>();
for (Type t : inferenceContext.restvars()) {
nodes.add(new Node(t));
}
//add dependencies
for (Node n_i : nodes) {
Type i = n_i.data.first();
Set<Type> optDepsByNode = stuckDeps.get(i);
for (Node n_j : nodes) {
Type j = n_j.data.first();
UndetVar uv_i = (UndetVar)inferenceContext.asFree(i);
if (Type.containsAny(uv_i.getBounds(InferenceBound.values()), List.of(j))) {
//update i's deps
n_i.deps.add(n_j);
//update i's bound dependencies
n_i.addDependency(DependencyKind.BOUND, n_j);
}
if (optDepsByNode != null && optDepsByNode.contains(j)) {
//update i's stuck dependencies
n_i.addDependency(DependencyKind.STUCK, n_j);
}
}
}
//merge cyclic nodes
ArrayList<Node> acyclicNodes = new ArrayList<Node>();
for (List<? extends Node> conSubGraph : GraphUtils.tarjan(nodes)) {
if (conSubGraph.length() > 1) {
@ -1822,11 +2016,15 @@ public class Infer {
}
}
private void solve(GraphStrategy ss, Warner warn) {
solve(ss, new HashMap<Type, Set<Type>>(), warn);
}
/**
* Solve with given graph strategy.
*/
private void solve(GraphStrategy ss, Warner warn) {
GraphSolver s = new GraphSolver(this, warn);
private void solve(GraphStrategy ss, Map<Type, Set<Type>> stuckDeps, Warner warn) {
GraphSolver s = new GraphSolver(this, stuckDeps, warn);
s.solve(ss);
}
@ -1855,18 +2053,12 @@ public class Infer {
/**
* Solve at least one variable in given list.
*/
public void solveAny(List<Type> varsToSolve, Warner warn) {
checkWithinBounds(this, warn); //propagate bounds
List<Type> boundedVars = boundedVars().intersect(restvars()).intersect(varsToSolve);
if (boundedVars.isEmpty()) {
throw inferenceException.setMessage("cyclic.inference",
freeVarsIn(varsToSolve));
}
solve(new BestLeafSolver(boundedVars) {
public void solveAny(List<Type> varsToSolve, Map<Type, Set<Type>> optDeps, Warner warn) {
solve(new BestLeafSolver(varsToSolve.intersect(restvars())) {
public boolean done() {
return instvars().intersect(varsToSolve).nonEmpty();
}
}, warn);
}, optDeps, warn);
}
/**

View file

@ -568,8 +568,10 @@ public class Resolve {
currentResolutionContext,
warn);
currentResolutionContext.methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn),
DeferredAttr.DeferredAttrContext dc = currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn);
currentResolutionContext.methodCheck.argumentsAcceptable(env, dc,
argtypes, mt.getParameterTypes(), warn);
dc.complete();
return mt;
}
@ -1053,7 +1055,8 @@ public class Resolve {
DeferredType dt = (DeferredType) actual;
DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
return (e == null || e.speculativeTree == deferredAttr.stuckTree)
? false : mostSpecific(found, req, e.speculativeTree, warn);
? super.compatible(found, req, warn) :
mostSpecific(found, req, e.speculativeTree, warn);
default:
return standaloneMostSpecific(found, req, actual, warn);
}
@ -1125,13 +1128,15 @@ public class Resolve {
@Override
public void visitReference(JCMemberReference tree) {
if (types.isFunctionalInterface(t.tsym) &&
types.isFunctionalInterface(s.tsym) &&
types.asSuper(t, s.tsym) == null &&
types.asSuper(s, t.tsym) == null) {
types.isFunctionalInterface(s.tsym)) {
Type desc_t = types.findDescriptorType(t);
Type desc_s = types.findDescriptorType(s);
if (types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
if (!desc_s.getReturnType().hasTag(VOID)) {
if (types.isSameTypes(desc_t.getParameterTypes(),
inferenceContext().asFree(desc_s.getParameterTypes()))) {
if (types.asSuper(t, s.tsym) != null ||
types.asSuper(s, t.tsym) != null) {
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
} else if (!desc_s.getReturnType().hasTag(VOID)) {
//perform structural comparison
Type ret_t = desc_t.getReturnType();
Type ret_s = desc_s.getReturnType();
@ -1141,25 +1146,24 @@ public class Resolve {
} else {
return;
}
} else {
result &= false;
}
} else {
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
result &= false;
}
}
@Override
public void visitLambda(JCLambda tree) {
if (types.isFunctionalInterface(t.tsym) &&
types.isFunctionalInterface(s.tsym) &&
types.asSuper(t, s.tsym) == null &&
types.asSuper(s, t.tsym) == null) {
types.isFunctionalInterface(s.tsym)) {
Type desc_t = types.findDescriptorType(t);
Type desc_s = types.findDescriptorType(s);
if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT
|| types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
if (!desc_s.getReturnType().hasTag(VOID)) {
if (types.isSameTypes(desc_t.getParameterTypes(),
inferenceContext().asFree(desc_s.getParameterTypes()))) {
if (types.asSuper(t, s.tsym) != null ||
types.asSuper(s, t.tsym) != null) {
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
} else if (!desc_s.getReturnType().hasTag(VOID)) {
//perform structural comparison
Type ret_t = desc_t.getReturnType();
Type ret_s = desc_s.getReturnType();
@ -1167,11 +1171,9 @@ public class Resolve {
} else {
return;
}
} else {
result &= false;
}
} else {
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
result &= false;
}
}
//where
@ -1521,7 +1523,8 @@ public class Resolve {
currentResolutionContext = prevResolutionContext;
}
}
private List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) {
List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) {
if ((msym.flags() & VARARGS) != 0 && allowVarargs) {
Type varargsElem = types.elemtype(args.last());
if (varargsElem == null) {
@ -2241,13 +2244,14 @@ public class Resolve {
public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
return (syms.operatorNames.contains(name)) ?
argtypes :
Type.map(argtypes, new ResolveDeferredRecoveryMap(accessedSym));
Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
}
};
class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap {
public ResolveDeferredRecoveryMap(Symbol msym) {
deferredAttr.super(AttrMode.SPECULATIVE, msym, currentResolutionContext.step);
public ResolveDeferredRecoveryMap(AttrMode mode, Symbol msym, MethodResolutionPhase step) {
deferredAttr.super(mode, msym, step);
}
@Override
@ -2266,7 +2270,6 @@ public class Resolve {
return res;
}
}
};
/** Check that sym is not an abstract method.
*/
@ -3969,16 +3972,6 @@ public class Resolve {
static {
String argMismatchRegex = MethodCheckDiag.ARG_MISMATCH.regex();
rewriters.put(new Template(argMismatchRegex, new Template("(.*)(bad.arg.types.in.lambda)", skip, skip)),
new DiagnosticRewriter() {
@Override
public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
DiagnosticType preferredKind, JCDiagnostic d) {
return (JCDiagnostic)((JCDiagnostic)d.getArgs()[0]).getArgs()[1];
}
});
rewriters.put(new Template(argMismatchRegex, skip),
new DiagnosticRewriter() {
@Override

View file

@ -742,11 +742,6 @@ compiler.misc.incompatible.arg.types.in.lambda=\
compiler.misc.incompatible.arg.types.in.mref=\
incompatible parameter types in method reference
# 0: list of type, 1: message segment
compiler.misc.bad.arg.types.in.lambda=\
cannot type-check lambda expression with inferred parameter types\n\
inferred types: {0}
compiler.err.new.not.allowed.in.annotation=\
''new'' not allowed in an annotation
@ -1397,6 +1392,10 @@ compiler.warn.long.SVUID=\
compiler.warn.missing.SVUID=\
serializable class {0} has no definition of serialVersionUID
# 0: symbol, 1: symbol, 2: symbol, 3: symbol
compiler.warn.potentially.ambiguous.overload=\
{0} in {1} is potentially ambiguous with {2} in {3}
# 0: message segment
compiler.warn.override.varargs.missing=\
{0}; overridden method has no ''...''
@ -1916,10 +1915,6 @@ compiler.misc.inferred.do.not.conform.to.eq.bounds=\
inferred: {0}\n\
equality constraints(s): {1}
# 0: list of type
compiler.misc.cyclic.inference=\
Cannot instantiate inference variables {0} because of an inference loop
# 0: symbol
compiler.misc.diamond=\
{0}<>

View file

@ -1908,6 +1908,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
* Selects a member expression.
*/
public static class JCMemberReference extends JCFunctionalExpression implements MemberReferenceTree {
public ReferenceMode mode;
public ReferenceKind kind;
public Name name;
@ -1917,6 +1918,12 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public Type varargsElement;
public PolyKind refPolyKind;
public boolean ownerAccessible;
public OverloadKind overloadKind;
public enum OverloadKind {
OVERLOADED,
UNOVERLOADED;
}
/**
* Javac-dependent classification for member references, based

View file

@ -32,6 +32,18 @@ package com.sun.tools.javac.util;
*/
public class GraphUtils {
/**
* Basic interface for defining various dependency kinds. All dependency kinds
* must at least support basic capabilities to tell the DOT engine how to render them.
*/
public interface DependencyKind {
/**
* Returns the DOT representation (to be used in a {@code style} attribute
* that's most suited for this dependency kind.
*/
String getDotStyle();
}
/**
* This class is a basic abstract class for representing a node.
* A node is associated with a given data.
@ -43,9 +55,20 @@ public class GraphUtils {
this.data = data;
}
public abstract Iterable<? extends Node<D>> getDependencies();
/**
* Get an array of the dependency kinds supported by this node.
*/
public abstract DependencyKind[] getSupportedDependencyKinds();
public abstract String printDependency(Node<D> to);
/**
* Get all dependencies, regardless of their kind.
*/
public abstract Iterable<? extends Node<D>> getAllDependencies();
/**
* Get a name for the dependency (of given kind) linking this node to a given node
*/
public abstract String getDependencyName(Node<D> to, DependencyKind dk);
@Override
public String toString() {
@ -66,7 +89,9 @@ public class GraphUtils {
super(data);
}
public abstract Iterable<? extends TarjanNode<D>> getDependencies();
public abstract Iterable<? extends TarjanNode<D>> getAllDependencies();
public abstract Iterable<? extends TarjanNode<D>> getDependenciesByKind(DependencyKind dk);
public int compareTo(TarjanNode<D> o) {
return (index < o.index) ? -1 : (index == o.index) ? 0 : 1;
@ -95,7 +120,7 @@ public class GraphUtils {
index++;
stack.prepend(v);
v.active = true;
for (TarjanNode<D> nd: v.getDependencies()) {
for (TarjanNode<D> nd: v.getAllDependencies()) {
@SuppressWarnings("unchecked")
N n = (N)nd;
if (n.index == -1) {
@ -134,9 +159,11 @@ public class GraphUtils {
}
//dump arcs
for (TarjanNode<D> from : nodes) {
for (TarjanNode<D> to : from.getDependencies()) {
buf.append(String.format("%s -> %s [label = \" %s \"];\n",
from.hashCode(), to.hashCode(), from.printDependency(to)));
for (DependencyKind dk : from.getSupportedDependencyKinds()) {
for (TarjanNode<D> to : from.getDependenciesByKind(dk)) {
buf.append(String.format("%s -> %s [label = \" %s \" style = %s ];\n",
from.hashCode(), to.hashCode(), from.getDependencyName(to, dk), dk.getDotStyle()));
}
}
}
buf.append("}\n");

View file

@ -116,6 +116,19 @@ public class List<A> extends AbstractCollection<A> implements java.util.List<A>
return buf.toList();
}
/**
* Create a new list from the first {@code n} elements of this list
*/
public List<A> take(int n) {
ListBuffer<A> buf = ListBuffer.lb();
int count = 0;
for (A el : this) {
if (count++ == n) break;
buf.append(el);
}
return buf.toList();
}
/** Construct a list consisting of given element.
*/
public static <A> List<A> of(A x1) {

View file

@ -1,3 +1,2 @@
T8012003c.java:18:15: compiler.err.report.access: m(), private, P
- compiler.note.compressed.diags
1 error

View file

@ -21,9 +21,6 @@
* questions.
*/
// key: compiler.err.cant.apply.symbol
// key: compiler.misc.no.conforming.assignment.exists
// key: compiler.misc.bad.arg.types.in.lambda
// key: compiler.err.prob.found.req
// key: compiler.misc.inconvertible.types
// options: -Xdiags:verbose

View file

@ -31,6 +31,7 @@ class IncompatibleArgTypesInMethodRef {
}
void g(String s, Integer i) { }
void g(Integer i, String s) { }
<Z> void m(SAM<Z> s) { }

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* 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
@ -21,17 +21,18 @@
* questions.
*/
// key: compiler.err.prob.found.req
// key: compiler.misc.cyclic.inference
// key: compiler.warn.potentially.ambiguous.overload
// options: -Xlint:overloads
class CyclicInference {
interface SAM<X> {
void m(X x);
class PotentiallyAmbiguousOverload {
interface F1 {
void m(String s);
}
<Z> void g(SAM<Z> sz) { }
void test() {
g(x-> {});
interface F2 {
void m(Integer s);
}
void m(F1 f1) { }
void m(F2 f2) { }
}

View file

@ -0,0 +1,45 @@
/*
* @test /nodynamiccopyright/
* @bug 8016177 8016178
* @summary structural most specific and stuckness
* @compile/fail/ref=T8016177a.out -XDrawDiagnostics T8016177a.java
*/
import java.util.List;
class T8016177a {
interface ToIntFunction<X> {
int m(X x);
}
interface Function<X, Y> {
Y m(X x);
}
<T,R> void m1(List<T> s, Function<T,R> f) { }
<T,R> void m1(List<T> s, ToIntFunction<T> f) { }
<T,R> List<R> m2(List<T> s, Function<T,R> f) { return null; }
<T,R> List<R> m2(List<T> s, ToIntFunction<T> f) { return null; }
<T,R> List<T> m3(List<T> s, Function<T,R> f) { return null; }
<T,R> List<R> m3(List<T> s, ToIntFunction<T> f) { return null; }
<T,R> List<T> m4(List<T> s, Function<T,R> f) { return null; }
<T,R> List<T> m4(List<T> s, ToIntFunction<T> f) { return null; }
<T,R> List<R> m5(List<T> s, Function<T,R> f) { return null; }
<T,R> List<T> m5(List<T> s, ToIntFunction<T> f) { return null; }
<T extends R,R> List<R> m6(List<T> s, Function<T,R> f) { return null; }
<T extends R,R> List<T> m6(List<T> s, ToIntFunction<T> f) { return null; }
void test(List<String> ss) {
m1(ss, s->s.length()); //ambiguous
m2(ss, s->s.length()); //ambiguous
m3(ss, s->s.length()); //ambiguous
m4(ss, s->s.length()); //ambiguous
m5(ss, s->s.length()); //ambiguous
m6(ss, s->s.length()); //ambiguous
}
}

View file

@ -0,0 +1,8 @@
T8016177a.java:38:10: compiler.err.ref.ambiguous: m1, kindname.method, <T,R>m1(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m1(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
T8016177a.java:39:10: compiler.err.ref.ambiguous: m2, kindname.method, <T,R>m2(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m2(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
T8016177a.java:40:10: compiler.err.ref.ambiguous: m3, kindname.method, <T,R>m3(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m3(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
T8016177a.java:41:10: compiler.err.ref.ambiguous: m4, kindname.method, <T,R>m4(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m4(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
T8016177a.java:42:10: compiler.err.ref.ambiguous: m5, kindname.method, <T,R>m5(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m5(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
T8016177a.java:43:10: compiler.err.ref.ambiguous: m6, kindname.method, <T,R>m6(java.util.List<T>,T8016177a.Function<T,R>), T8016177a, kindname.method, <T,R>m6(java.util.List<T>,T8016177a.ToIntFunction<T>), T8016177a
T8016177a.java:43:12: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,R, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, java.lang.String)))
7 errors

View file

@ -0,0 +1,34 @@
/*
* @test /nodynamiccopyright/
* @bug 8016177 8016178
* @summary structural most specific and stuckness
* @compile/fail/ref=T8016177b.out -XDrawDiagnostics T8016177b.java
*/
class T8016177b {
interface ToIntFunction<X> {
int m(X x);
}
interface Function<X, Y> {
Y m(X x);
}
<U, V> Function<U, V> id(Function<U, V> arg) { return null; }
<U, V> Function<U, V> id2(Function<U, V> arg) { return null; }
<U> ToIntFunction<U> id2(ToIntFunction<U> arg) { return null; }
<X,Y,Z> X f(Y arg, Function<Y, Z> f) { return null; }
<X,Y,Z> X f2(Y arg, Function<Y, Z> f) { return null; }
<X,Y> X f2(Y arg, ToIntFunction<Y> f) { return null; }
<T> T g(T arg) { return null; }
void test() {
g(f("hi", id(x->1))); //ok
g(f("hi", id2(x->1))); //ambiguous
g(f2("hi", id(x->1))); //ok
}
}

View file

@ -0,0 +1,2 @@
T8016177b.java:31:19: compiler.err.ref.ambiguous: id2, kindname.method, <U,V>id2(T8016177b.Function<U,V>), T8016177b, kindname.method, <U>id2(T8016177b.ToIntFunction<U>), T8016177b
1 error

View file

@ -0,0 +1,47 @@
/*
* @test /nodynamiccopyright/
* @bug 8016081 8016178
* @summary structural most specific and stuckness
* @compile/fail/ref=T8016177c.out -XDrawDiagnostics T8016177c.java
*/
class T8016177c {
interface Function<X, Y> {
Y m(X x);
}
interface ExtFunction<X, Y> extends Function<X, Y> { }
<U, V> U m1(Function<U, V> f) { return null; }
<U, V> U m1(ExtFunction<U, V> f) { return null; }
void m2(Function<Integer, Integer> f) { }
void m2(ExtFunction<Integer, Integer> f) { }
void m3(Function<Integer, Integer> f) { }
void m3(ExtFunction<Object, Integer> f) { }
int g1(Object s) { return 1; }
int g2(Number s) { return 1; }
int g2(Object s) { return 1; }
void test() {
m1((Integer x)->x); //ok - explicit lambda - subtyping picks most specific
m2((Integer x)->x); //ok - explicit lambda - subtyping picks most specific
m3((Integer x)->x); //ok - explicit lambda (only one applicable)
m1(x->1); //ok - stuck lambda but nominal most specific wins
m2(x->1); //ok - stuck lambda but nominal most specific wins
m3(x->1); //ambiguous - implicit lambda & different params
m1(this::g1); //ok - unambiguous ref - subtyping picks most specific
m2(this::g1); //ok - unambiguous ref - subtyping picks most specific
m3(this::g1); //ambiguous - both applicable, neither most specific
m1(this::g2); //ok - stuck mref but nominal most specific wins
m2(this::g2); //ok - stuck mref but nominal most specific wins
m3(this::g2); //ambiguous - different params
}
}

View file

@ -0,0 +1,4 @@
T8016177c.java:37:9: compiler.err.ref.ambiguous: m3, kindname.method, m3(T8016177c.Function<java.lang.Integer,java.lang.Integer>), T8016177c, kindname.method, m3(T8016177c.ExtFunction<java.lang.Object,java.lang.Integer>), T8016177c
T8016177c.java:41:9: compiler.err.ref.ambiguous: m3, kindname.method, m3(T8016177c.Function<java.lang.Integer,java.lang.Integer>), T8016177c, kindname.method, m3(T8016177c.ExtFunction<java.lang.Object,java.lang.Integer>), T8016177c
T8016177c.java:45:9: compiler.err.ref.ambiguous: m3, kindname.method, m3(T8016177c.Function<java.lang.Integer,java.lang.Integer>), T8016177c, kindname.method, m3(T8016177c.ExtFunction<java.lang.Object,java.lang.Integer>), T8016177c
3 errors

View file

@ -0,0 +1,58 @@
/*
* 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 8016081 8016178
* @summary structural most specific and stuckness
* @compile T8016177d.java
*/
import java.util.*;
class T8016177d {
interface UnaryOperator<X> {
X m(X x);
}
interface IntStream {
IntStream sorted();
IntStream distinct();
IntStream limit(int i);
}
abstract class WrappingUnaryOperator<S> implements UnaryOperator<S> { }
<S1> WrappingUnaryOperator<S1> wrap1(UnaryOperator<S1> uo) { return null; }
<S2> WrappingUnaryOperator<S2> wrap2(UnaryOperator<S2> uo) { return null; }
<S3> WrappingUnaryOperator<S3> wrap3(UnaryOperator<S3> uo) { return null; }
<P> List<List<P>> perm(List<P> l) { return null; }
List<List<WrappingUnaryOperator<IntStream>>> intPermutationOfFunctions =
perm(Arrays.asList(
wrap1(s -> s.sorted()),
wrap2(s -> s.distinct()),
wrap3(s -> s.limit(5))
));
}

View file

@ -0,0 +1,46 @@
/*
* 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 8016081 8016178
* @summary structural most specific and stuckness
* @compile T8016177e.java
*/
import java.util.*;
class T8016177e {
interface TerminalOp<X, Y> { }
interface Consumer<X> {
void m(X x);
}
<T> TerminalOp<T, Void> makeRef(Consumer<? super T> action) { return null; }
<T> void test() {
Map<T, Boolean> map = null;
TerminalOp<T, Void> forEachOp = makeRef(t -> { map.put(t, null); });
}
}

View file

@ -0,0 +1,94 @@
/*
* 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 8016081 8016178
* @summary structural most specific and stuckness
* @compile T8016177f.java
*/
import java.util.*;
class T8016177f {
interface Function<S, T> {
T apply(S s);
}
interface IntFunction<T> {
T apply(int s);
}
interface BiConsumer<X,Y> {
void m(X x, Y y);
}
interface Consumer<X> {
void m(X x);
}
interface Supplier<X> {
X make();
}
interface TestData<T, S extends BaseStream<T, S>> {
interface OfRef<T> extends TestData<T, Stream<T>> { }
interface OfDouble extends TestData<Double, DoubleStream> { }
}
interface BaseStream<T, S extends BaseStream<T, S>> { }
interface Stream<T> extends BaseStream<T, Stream<T>> {
<M> Stream<M> map(Function<T, M> s);
<R> R collect(Supplier<R> resultFactory, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
<Z> Z[] toArray(IntFunction<Z[]> s);
}
interface DoubleStream extends BaseStream<Double, DoubleStream> {
DoubleStream filter(DoublePredicate dp);
double[] toArray();
}
interface DoublePredicate {
boolean p(double d);
}
<T, U, R, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>>
R exerciseTerminalOps(TestData<T, S_IN> data,
Function<S_IN, S_OUT> streamF,
Function<S_OUT, R> terminalF) { return null; }
<O> TestData.OfRef<O> ofCollection(Collection<O> collection) { return null; }
void test1(TestData.OfDouble data, DoublePredicate dp) {
exerciseTerminalOps(data, s -> s.filter(dp), s -> s.toArray());
}
void test2(Function<Double, Integer> fdi, TestData.OfRef<Double> td, Stream<Integer> si) {
exerciseTerminalOps(
ofCollection((List<Double>)null),
s -> s.map(fdi),
s -> s.toArray(Integer[]::new));
}
}

View file

@ -0,0 +1,37 @@
/*
* @test /nodynamiccopyright/
* @bug 8016081 8016178
* @summary structural most specific and stuckness
* @compile/fail/ref=T8016177g.out -XDrawDiagnostics T8016177g.java
*/
class Test {
interface Function<X, Y> {
Y m(X x);
}
interface Box<T> {
T get();
<R> R map(Function<T,R> f);
}
static class Person {
Person(String name) { }
}
void print(Object arg) { }
void print(String arg) { }
int abs(int a) { return 0; }
long abs(long a) { return 0; }
float abs(float a) { return 0; }
double abs(double a) { return 0; }
void test() {
Box<String> b = null;
print(b.map(s -> new Person(s)));
int i = abs(b.map(s -> Double.valueOf(s)));
}
}

View file

@ -0,0 +1,2 @@
T8016177g.java:35:20: compiler.err.prob.found.req: (compiler.misc.possible.loss.of.precision: double, int)
1 error

View file

@ -1,2 +1,3 @@
BadRecovery.java:17:9: compiler.err.cant.apply.symbol: kindname.method, m, BadRecovery.SAM1, @369, kindname.class, BadRecovery, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.lambda))
BadRecovery.java:17:77: compiler.err.cant.resolve.location: kindname.variable, f, , , (compiler.misc.location: kindname.class, BadRecovery, null)
1 error
2 errors

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -26,6 +26,7 @@
* @bug 8003280
* @summary Add lambda tests
* stale state after speculative attribution round leads to missing classfiles
* @compile/fail/ref=ErroneousLambdaExpr.out -XDrawDiagnostics ErroneousLambdaExpr.java
*/
public class ErroneousLambdaExpr<T> {

View file

@ -0,0 +1,2 @@
ErroneousLambdaExpr.java:63:13: compiler.err.ref.ambiguous: call, kindname.method, call(ErroneousLambdaExpr.SAM1<T>), ErroneousLambdaExpr, kindname.method, call(ErroneousLambdaExpr.SAM2), ErroneousLambdaExpr
1 error

View file

@ -3,13 +3,17 @@ MethodReference22.java:41:15: compiler.err.invalid.mref: kindname.method, (compi
MethodReference22.java:46:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String))
MethodReference22.java:47:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String))
MethodReference22.java:51:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22))
MethodReference22.java:52:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1401, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22)))
MethodReference22.java:52:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1401, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22)))
MethodReference22.java:53:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22))
MethodReference22.java:54:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1504, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22)))
MethodReference22.java:54:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1504, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22)))
MethodReference22.java:55:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22))
MethodReference22.java:56:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1607, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22)))
MethodReference22.java:56:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1607, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22)))
MethodReference22.java:57:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22))
MethodReference22.java:58:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1710, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22)))
MethodReference22.java:58:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1710, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22)))
MethodReference22.java:62:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
MethodReference22.java:62:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m1(java.lang.String))
MethodReference22.java:63:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
MethodReference22.java:64:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
MethodReference22.java:65:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
MethodReference22.java:65:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String))
14 errors
18 errors

View file

@ -1,6 +1,6 @@
MethodReference23.java:52:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23))
MethodReference23.java:53:9: compiler.err.cant.apply.symbol: kindname.method, call11, MethodReference23.SAM11, @1140, kindname.class, MethodReference23, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23)))
MethodReference23.java:53:15: compiler.err.cant.apply.symbol: kindname.method, call11, MethodReference23.SAM11, @1140, kindname.class, MethodReference23, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23)))
MethodReference23.java:57:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23))
MethodReference23.java:58:9: compiler.err.cant.apply.symbol: kindname.method, call12, MethodReference23.SAM12, @1282, kindname.class, MethodReference23, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23)))
MethodReference23.java:58:15: compiler.err.cant.apply.symbol: kindname.method, call12, MethodReference23.SAM12, @1282, kindname.class, MethodReference23, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23)))
MethodReference23.java:72:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference23.SAM21), MethodReference23, kindname.method, call3(MethodReference23.SAM22), MethodReference23
5 errors

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -26,18 +26,10 @@
* @bug 8003280
* @summary Add lambda tests
* check that diamond inference is applied when using raw constructor reference qualifier
* @run main MethodReference41
* @compile/fail/ref=MethodReference41.out -XDrawDiagnostics MethodReference41.java
*/
public class MethodReference41 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
interface SAM1 {
void m(String s);
}
@ -54,13 +46,20 @@ public class MethodReference41 {
Foo(X x) { }
}
static void m1(SAM1 s) { }
static void m(SAM1 s) { assertTrue(false); }
static void m(SAM2 s) { assertTrue(true); }
static void m(SAM3 s) { assertTrue(false); }
static void m2(SAM2 s) { }
static void m3(SAM3 s) { }
static void m4(SAM1 s) { }
static void m4(SAM2 s) { }
static void m4(SAM3 s) { }
public static void main(String[] args) {
m(Foo::new);
assertTrue(assertionCount == 1);
m1(Foo::new);
m2(Foo::new);
m3(Foo::new);
m4(Foo::new);
}
}

View file

@ -0,0 +1,4 @@
MethodReference41.java:60:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference41.SAM1, @1819, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference41.Foo<X>, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Number))))
MethodReference41.java:62:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference41.SAM3, @1863, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference41.Foo<X>, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Number))))
MethodReference41.java:63:9: compiler.err.ref.ambiguous: m4, kindname.method, m4(MethodReference41.SAM2), MethodReference41, kindname.method, m4(MethodReference41.SAM3), MethodReference41
3 errors

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -26,18 +26,10 @@
* @bug 8003280
* @summary Add lambda tests
* check that diamond inference is applied when using raw constructor reference qualifier
* @run main MethodReference42
* @compile/fail/ref=MethodReference42.out -XDrawDiagnostics MethodReference42.java
*/
public class MethodReference42 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
static class SuperFoo<X> { }
static class Foo<X extends Number> extends SuperFoo<X> { }
@ -54,12 +46,20 @@ public class MethodReference42 {
SuperFoo<Object> m();
}
static void m(SAM1 s) { assertTrue(false); }
static void m(SAM2 s) { assertTrue(true); }
static void m(SAM3 s) { assertTrue(false); }
static void m1(SAM1 s) { }
static void m2(SAM2 s) { }
static void m3(SAM3 s) { }
static void m4(SAM1 s) { }
static void m4(SAM2 s) { }
static void m4(SAM3 s) { }
public static void main(String[] args) {
m(Foo::new);
assertTrue(assertionCount == 1);
m1(Foo::new);
m2(Foo::new);
m3(Foo::new);
m4(Foo::new);
}
}

View file

@ -0,0 +1,4 @@
MethodReference42.java:60:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference42.SAM1, @1851, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number))
MethodReference42.java:62:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference42.SAM3, @1895, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Number))
MethodReference42.java:63:9: compiler.err.ref.ambiguous: m4, kindname.method, m4(MethodReference42.SAM2), MethodReference42, kindname.method, m4(MethodReference42.SAM3), MethodReference42
3 errors

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -26,18 +26,10 @@
* @bug 8003280
* @summary Add lambda tests
* check that diamond inference is applied when using raw constructor reference qualifier
* @run main MethodReference43
* @compile/fail/ref=MethodReference43.out -XDrawDiagnostics MethodReference43.java
*/
public class MethodReference43 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
interface SAM1 {
Foo<?> m(String s);
}
@ -58,14 +50,24 @@ public class MethodReference43 {
Foo(X x) { }
}
static void m1(SAM1 s) { }
static void m(SAM1 s) { assertTrue(false); }
static void m(SAM2 s) { assertTrue(false); }
static void m(SAM3 s) { assertTrue(false); }
static void m(SAM4 s) { assertTrue(true); }
static void m2(SAM2 s) { }
static void m3(SAM3 s) { }
static void m4(SAM4 s) { }
static void m5(SAM1 s) { }
static void m5(SAM2 s) { }
static void m5(SAM3 s) { }
static void m5(SAM4 s) { }
public static void main(String[] args) {
m(Foo::new);
assertTrue(assertionCount == 1);
m1(Foo::new);
m2(Foo::new);
m3(Foo::new);
m4(Foo::new);
m5(Foo::new);
}
}

View file

@ -0,0 +1,5 @@
MethodReference43.java:67:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference43.SAM1, @1937, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference43.Foo<X>, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Number))))
MethodReference43.java:69:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference43.SAM3, @1981, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Number))))
MethodReference43.java:71:9: compiler.err.ref.ambiguous: m5, kindname.method, m5(MethodReference43.SAM3), MethodReference43, kindname.method, m5(MethodReference43.SAM4), MethodReference43
MethodReference43.java:71:11: compiler.err.cant.apply.symbol: kindname.method, m5, MethodReference43.SAM3, @2025, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Number))))
4 errors

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -26,18 +26,10 @@
* @bug 8003280
* @summary Add lambda tests
* check that generic method reference is inferred when type parameters are omitted
* @run main MethodReference44
* @compile/fail/ref=MethodReference44.out -XDrawDiagnostics MethodReference44.java
*/
public class MethodReference44 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
static class SuperFoo<X> { }
static class Foo<X extends Number> extends SuperFoo<X> { }
@ -56,12 +48,20 @@ public class MethodReference44 {
static <X extends Number> Foo<X> m() { return null; }
static void g(SAM1 s) { assertTrue(false); }
static void g(SAM2 s) { assertTrue(true); }
static void g(SAM3 s) { assertTrue(false); }
static void g1(SAM1 s) { }
static void g2(SAM2 s) { }
static void g3(SAM3 s) { }
static void g4(SAM1 s) { }
static void g4(SAM2 s) { }
static void g4(SAM3 s) { }
public static void main(String[] args) {
g(MethodReference44::m);
assertTrue(assertionCount == 1);
g1(MethodReference44::m);
g2(MethodReference44::m);
g3(MethodReference44::m);
g4(MethodReference44::m);
}
}

View file

@ -0,0 +1,4 @@
MethodReference44.java:62:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference44.SAM1, @1904, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number))
MethodReference44.java:64:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference44.SAM3, @1972, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Number))
MethodReference44.java:65:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference44.SAM2), MethodReference44, kindname.method, g4(MethodReference44.SAM3), MethodReference44
3 errors

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -26,18 +26,10 @@
* @bug 8003280
* @summary Add lambda tests
* check that generic method reference is inferred when type parameters are omitted
* @run main MethodReference46
* @compile/fail/ref=MethodReference46.out -XDrawDiagnostics MethodReference46.java
*/
public class MethodReference46 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
interface SAM1 {
void m(String s);
}
@ -56,12 +48,20 @@ public class MethodReference46 {
static <X extends Number> void m(X fx) { }
static void g(SAM1 s) { assertTrue(false); }
static void g(SAM2 s) { assertTrue(true); }
static void g(SAM3 s) { assertTrue(false); }
static void g1(SAM1 s) { }
static void g2(SAM2 s) { }
static void g3(SAM3 s) { }
static void g4(SAM1 s) { }
static void g4(SAM2 s) { }
static void g4(SAM3 s) { }
public static void main(String[] args) {
g(MethodReference46::m);
assertTrue(assertionCount == 1);
g1(MethodReference46::m);
g2(MethodReference46::m);
g3(MethodReference46::m);
g4(MethodReference46::m);
}
}

View file

@ -0,0 +1,4 @@
MethodReference46.java:62:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference46.SAM1, @1849, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.String, kindname.class, MethodReference46, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Number))))
MethodReference46.java:64:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference46.SAM3, @1917, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.Object, kindname.class, MethodReference46, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Number))))
MethodReference46.java:65:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference46.SAM2), MethodReference46, kindname.method, g4(MethodReference46.SAM3), MethodReference46
3 errors

View file

@ -7,14 +7,6 @@
*/
public class MethodReference47 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
interface SAM1 {
void m(Integer s);
}
@ -34,7 +26,7 @@ public class MethodReference47 {
static void g2(SAM2 s) { }
public static void main(String[] args) {
g1(MethodReference46::m);
g2(MethodReference46::m);
g1(MethodReference47::m);
g2(MethodReference47::m);
}
}

View file

@ -1,2 +1,2 @@
MethodReference47.java:38:9: compiler.err.ref.ambiguous: g2, kindname.method, g2(MethodReference47.SAM1), MethodReference47, kindname.method, g2(MethodReference47.SAM2), MethodReference47
MethodReference47.java:30:9: compiler.err.ref.ambiguous: g2, kindname.method, g2(MethodReference47.SAM1), MethodReference47, kindname.method, g2(MethodReference47.SAM2), MethodReference47
1 error

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -26,18 +26,10 @@
* @bug 8003280
* @summary Add lambda tests
* check that raw qualifier in unbound method reference is inferred from descriptor
* @run main MethodReference48
* @compile/fail/ref=MethodReference48.out -XDrawDiagnostics MethodReference48.java
*/
public class MethodReference48 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
static class Foo<X> {
X m() { return null; };
}
@ -54,12 +46,20 @@ public class MethodReference48 {
Object m(Foo<Integer> fi);
}
static void g(SAM1 s) { assertTrue(false); } //return type not compatible
static void g(SAM2 s) { assertTrue(true); } //ok
static void g(SAM3 s) { assertTrue(false); } //ok but less specific
static void g1(SAM1 s) { } //return type not compatible
static void g2(SAM2 s) { } //ok
static void g3(SAM3 s) { } //ok
static void g4(SAM1 s) { } //return type not compatible
static void g4(SAM2 s) { } //ok
static void g4(SAM3 s) { } //ok
public static void main(String[] args) {
g(Foo::m);
assertTrue(assertionCount == 1);
g1(Foo::m);
g2(Foo::m);
g3(Foo::m);
g4(Foo::m);
}
}

View file

@ -0,0 +1,3 @@
MethodReference48.java:60:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference48.SAM1, @1909, kindname.class, MethodReference48, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: java.lang.String, MethodReference48.Foo<java.lang.Object>)))
MethodReference48.java:63:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference48.SAM2), MethodReference48, kindname.method, g4(MethodReference48.SAM3), MethodReference48
2 errors

View file

@ -1,3 +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)
MethodReference70.java:26:11: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbols: kindname.method, m2, java.lang.Object,{(compiler.misc.inapplicable.method: kindname.method, MethodReference70, m2(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer))),(compiler.misc.inapplicable.method: kindname.method, MethodReference70, m2(java.lang.String), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))})))
2 errors

View file

@ -1,3 +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)
MethodReference71.java:24:11: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m2, java.lang.Integer[], java.lang.Object, kindname.class, MethodReference71, (compiler.misc.varargs.argument.mismatch: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer)))))
2 errors

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -26,17 +26,10 @@
* @bug 8003280
* @summary Add lambda tests
* Structural most specific doesn't handle cases with wildcards in functional interfaces
* @compile/fail/ref=MostSpecific04.out -XDrawDiagnostics MostSpecific04.java
*/
public class MostSpecific04 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
interface DoubleMapper<T> {
double map(T t);
}
@ -46,13 +39,13 @@ public class MostSpecific04 {
}
static class MyList<E> {
void map(DoubleMapper<? super E> m) { assertTrue(false); }
void map(LongMapper<? super E> m) { assertTrue(true); }
void map(DoubleMapper<? super E> m) { }
void map(LongMapper<? super E> m) { }
}
public static void main(String[] args) {
MyList<String> ls = new MyList<String>();
ls.map(e->e.length());
assertTrue(assertionCount == 1);
ls.map(e->e.length()); //ambiguous - implicit
ls.map((String e)->e.length()); //ok
}
}

View file

@ -0,0 +1,2 @@
MostSpecific04.java:48:11: compiler.err.ref.ambiguous: map, kindname.method, map(MostSpecific04.DoubleMapper<? super E>), MostSpecific04.MyList, kindname.method, map(MostSpecific04.LongMapper<? super E>), MostSpecific04.MyList
1 error

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -26,17 +26,10 @@
* @bug 8003280
* @summary Add lambda tests
* Structural most specific doesn't handle cases with wildcards in functional interfaces
* @compile/fail/ref=MostSpecific05.out -XDrawDiagnostics MostSpecific05.java
*/
public class MostSpecific05 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
interface ObjectConverter<T extends Object> {
T map(Object o);
}
@ -46,13 +39,13 @@ public class MostSpecific05 {
}
static class MyMapper<A extends Object, B extends Number> {
void map(ObjectConverter<? extends A> m) { assertTrue(false); }
void map(NumberConverter<? extends B> m) { assertTrue(true); }
void map(ObjectConverter<? extends A> m) { }
void map(NumberConverter<? extends B> m) { }
}
public static void main(String[] args) {
MyMapper<Number, Double> mm = new MyMapper<Number, Double>();
mm.map(e->1.0);
assertTrue(assertionCount == 1);
mm.map(e->1.0); //ambiguous - implicit
mm.map((Object e)->1.0); //ok
}
}

View file

@ -0,0 +1,2 @@
MostSpecific05.java:48:11: compiler.err.ref.ambiguous: map, kindname.method, map(MostSpecific05.ObjectConverter<? extends A>), MostSpecific05.MyMapper, kindname.method, map(MostSpecific05.NumberConverter<? extends B>), MostSpecific05.MyMapper
1 error

View file

@ -25,7 +25,7 @@
* @test
* @bug 8008813
* @summary Structural most specific fails when method reference is passed to overloaded method
* @compile MostSpecific08.java
* @compile/fail/ref=MostSpecific08.out -XDrawDiagnostics MostSpecific08.java
*/
class MostSpecific08 {
@ -51,12 +51,14 @@ class MostSpecific08 {
}
void testMref(Tester t) {
IntResult pr = t.apply(C::getInt);
ReferenceResult<Integer> rr = t.apply(C::getInteger);
IntResult pr = t.apply(C::getInt); //ok - unoverloaded mref
ReferenceResult<Integer> rr = t.apply(C::getInteger); //ok - unoverloaded mref
}
void testLambda(Tester t) {
IntResult pr = t.apply(c->c.getInt());
ReferenceResult<Integer> rr = t.apply(c->c.getInteger());
IntResult pr1 = t.apply(c->c.getInt()); //ambiguous - implicit
IntResult pr2 = t.apply((C c)->c.getInt()); //ok
ReferenceResult<Integer> rr1 = t.apply(c->c.getInteger()); //ambiguous - implicit
ReferenceResult<Integer> rr2 = t.apply((C c)->c.getInteger()); //ok
}
}

View file

@ -0,0 +1,4 @@
MostSpecific08.java:59:26: compiler.err.ref.ambiguous: apply, kindname.method, apply(MostSpecific08.PrimitiveFunction), MostSpecific08.Tester, kindname.method, <Z>apply(MostSpecific08.ReferenceFunction<Z>), MostSpecific08.Tester
MostSpecific08.java:61:41: compiler.err.ref.ambiguous: apply, kindname.method, apply(MostSpecific08.PrimitiveFunction), MostSpecific08.Tester, kindname.method, <Z>apply(MostSpecific08.ReferenceFunction<Z>), MostSpecific08.Tester
MostSpecific08.java:61:47: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: MostSpecific08.IntResult, MostSpecific08.ReferenceResult<java.lang.Integer>)
3 errors

View file

@ -26,7 +26,7 @@
* @bug 8003280 8009131
* @summary Add lambda tests
* check nested case of overload resolution and lambda parameter inference
* @compile TargetType01.java
* @compile/fail/ref=TargetType01.out -XDrawDiagnostics TargetType01.java
*/
class TargetType01 {

View file

@ -0,0 +1,3 @@
TargetType01.java:45:9: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01
TargetType01.java:45:26: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01
2 errors

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@ -27,19 +27,11 @@
* @summary Add lambda tests
* check overload resolution and target type inference w.r.t. generic methods
* @author Maurizio Cimadamore
* @run main TargetType02
* @compile/fail/ref=TargetType02.out -XDrawDiagnostics TargetType02.java
*/
public class TargetType02 {
static int assertionCount = 0;
static void assertTrue(boolean cond) {
assertionCount++;
if (!cond)
throw new AssertionError();
}
interface S1<X extends Number> {
X m(Integer x);
}
@ -48,15 +40,16 @@ public class TargetType02 {
abstract X m(Integer x);
}
static <Z extends Number> void call(S1<Z> s) { s.m(1); assertTrue(true); }
static <Z extends String> void call(S2<Z> s) { s.m(2); assertTrue(false); }
static <Z extends Number> void call1(S1<Z> s) { }
static <Z extends String> void call2(S2<Z> s) { }
static <Z extends Number> void call3(S1<Z> s) { }
static <Z extends String> void call3(S2<Z> s) { }
void test() {
call(i -> { toString(); return i; });
}
public static void main(String[] args) {
new TargetType02().test();
assertTrue(assertionCount == 1);
call1(i -> { toString(); return i; });
call2(i -> { toString(); return i; });
call3(i -> { toString(); return i; });
}
}

View file

@ -0,0 +1,3 @@
TargetType02.java:52:14: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, java.lang.String)
TargetType02.java:53:9: compiler.err.ref.ambiguous: call3, kindname.method, <Z>call3(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call3(TargetType02.S2<Z>), TargetType02
2 errors

View file

@ -1,10 +1,10 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @bug 8003280 8016177
* @summary Add lambda tests
* check that wildcards in the target method of a lambda conversion is handled correctly
* @author Maurizio Cimadamore
* @compile/fail/ref=TargetType10.out -XDrawDiagnostics TargetType10.java
* @compile TargetType10.java
*/
class TargetType10 {

View file

@ -1,2 +0,0 @@
TargetType10.java:17:18: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: B,A)
1 error

View file

@ -26,8 +26,10 @@ class TargetType21 {
void test() {
call(x -> { throw new Exception(); }); //ambiguous
call((Integer x) -> { System.out.println(""); }); //ok (only one is void)
call((Integer x) -> { return (Object) null; }); //ok (only one returns Object)
call(x -> { System.out.println(""); }); //ambiguous
call(x -> { return (Object) null; }); //cyclic inference
call(x -> { return (Object) null; }); //ambiguous
call(x -> { return null; }); //ambiguous
}
}

View file

@ -1,5 +1,7 @@
TargetType21.java:28:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
TargetType21.java:29:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
TargetType21.java:30:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: A)
TargetType21.java:31:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
4 errors
TargetType21.java:31:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
TargetType21.java:32:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
TargetType21.java:32:13: compiler.err.cant.apply.symbol: kindname.method, call, TargetType21.SAM2, @888, kindname.class, TargetType21, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))
TargetType21.java:33:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
TargetType21.java:33:13: compiler.err.cant.apply.symbol: kindname.method, call, TargetType21.SAM2, @946, kindname.class, TargetType21, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))
6 errors

View file

@ -29,11 +29,14 @@ class TargetType24 {
}
void test(Array<String> as, final Array<Character> ac) {
final boolean b1 = as.forAll(s -> ac.forAll(c -> false)); //ok
final boolean b1 = as.forAll((String s) -> ac.forAll((Character c) -> false)); //ok
final boolean b2 = as.forAll(s -> ac.forAll(c -> false)); //ambiguous
final boolean b3 = as.forAll((String s) -> ac.forAll(c -> false)); //ambiguous
final boolean b4 = as.forAll(s -> ac.forAll((Character c) -> false)); //ambiguous
final String s1 = as.forAll2(s -> ac.forAll2(c -> "")); //ok
final boolean b2 = as.forAll(s -> ac.forAll(c -> "" )); //fail
final boolean b5 = as.forAll(s -> ac.forAll(c -> "" )); //fail
final String s2 = as.forAll2(s -> ac.forAll2(c -> false)); //fail
final boolean b3 = as.forAll((F<String, Boolean>)s -> ac.forAll((F<Character, Boolean>)c -> "")); //fail
final boolean b6 = as.forAll((F<String, Boolean>)s -> ac.forAll((F<Character, Boolean>)c -> "")); //fail
final String s3 = as.forAll((FSub<String, String>)s -> ac.forAll((FSub<Character, String>)c -> false)); //fail
}
}

View file

@ -1,5 +1,11 @@
TargetType24.java:34:37: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, boolean)
TargetType24.java:35:45: compiler.err.cant.apply.symbol: kindname.method, forAll2, TargetType24.FSub<java.lang.Character,java.lang.String>, @945, kindname.class, TargetType24.Array<A>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: boolean, java.lang.String)))
TargetType24.java:36:101: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Boolean))
TargetType24.java:37:104: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: boolean, java.lang.String))
4 errors
TargetType24.java:33:30: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F<A,java.lang.Boolean>), TargetType24.Array, kindname.method, forAll(TargetType24.FSub<A,java.lang.String>), TargetType24.Array
TargetType24.java:33:45: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F<A,java.lang.Boolean>), TargetType24.Array, kindname.method, forAll(TargetType24.FSub<A,java.lang.String>), TargetType24.Array
TargetType24.java:34:54: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F<A,java.lang.Boolean>), TargetType24.Array, kindname.method, forAll(TargetType24.FSub<A,java.lang.String>), TargetType24.Array
TargetType24.java:35:30: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F<A,java.lang.Boolean>), TargetType24.Array, kindname.method, forAll(TargetType24.FSub<A,java.lang.String>), TargetType24.Array
TargetType24.java:37:30: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F<A,java.lang.Boolean>), TargetType24.Array, kindname.method, forAll(TargetType24.FSub<A,java.lang.String>), TargetType24.Array
TargetType24.java:37:45: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F<A,java.lang.Boolean>), TargetType24.Array, kindname.method, forAll(TargetType24.FSub<A,java.lang.String>), TargetType24.Array
TargetType24.java:37:52: compiler.err.cant.apply.symbol: kindname.method, forAll, TargetType24.F<java.lang.Character,java.lang.Boolean>, @1149, kindname.class, TargetType24.Array<A>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Boolean)))
TargetType24.java:38:53: compiler.err.cant.apply.symbol: kindname.method, forAll2, TargetType24.FSub<java.lang.Character,java.lang.String>, @1221, kindname.class, TargetType24.Array<A>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: boolean, java.lang.String)))
TargetType24.java:39:101: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Boolean))
TargetType24.java:40:104: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: boolean, java.lang.String))
10 errors

View file

@ -1,2 +1,2 @@
TargetType26.java:16:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z)
TargetType26.java:16:11: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.not.a.functional.intf: java.lang.Object))
1 error

View file

@ -1,2 +1,2 @@
TargetType27.java:18:10: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: R)
TargetType27.java:18:10: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: A,R, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.not.a.functional.intf: java.lang.Object)))
1 error

View file

@ -1,3 +1,3 @@
TargetType39.java:19:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: U)
TargetType39.java:20:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: V)
TargetType39.java:19:13: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: U,V, (compiler.misc.incompatible.type.in.conditional: (compiler.misc.inconvertible.types: TargetType39.SAM<java.lang.String,java.lang.Void>, TargetType39.SAM<java.lang.Object,V>)))
TargetType39.java:20:13: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: U,V, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.type.in.conditional: (compiler.misc.not.a.functional.intf: java.lang.Object))))
2 errors

View file

@ -1,4 +1,5 @@
TargetType43.java:13:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object)
TargetType43.java:13:30: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, TargetType43, null)
TargetType43.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.Object, @359, kindname.class, TargetType43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: java.lang.Object))
TargetType43.java:14:21: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, TargetType43, null)
3 errors
4 errors

View file

@ -17,8 +17,8 @@ class TargetType66 {
void g(SAM2 s2) { }
void test() {
g(x->{ String s = x; }); //g(SAM1)
g(x->{ Integer i = x; }); //g(SAM2)
g(x->{ String s = x; }); //ambiguous
g(x->{ Integer i = x; }); //ambiguous
g(x->{ Object o = x; }); //ambiguous
g(x->{ Character c = x; }); //error: inapplicable methods
g(x->{ Character c = ""; }); //error: incompatible types

View file

@ -1,4 +1,9 @@
TargetType66.java:20:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66
TargetType66.java:21:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66
TargetType66.java:21:28: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer)
TargetType66.java:22:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66
TargetType66.java:23:9: compiler.err.cant.apply.symbols: kindname.method, g, @578,{(compiler.misc.inapplicable.method: kindname.method, TargetType66, g(TargetType66.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.bad.arg.types.in.lambda: java.lang.String, (compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Character))))),(compiler.misc.inapplicable.method: kindname.method, TargetType66, g(TargetType66.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.bad.arg.types.in.lambda: java.lang.Integer, (compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.Character)))))}
TargetType66.java:23:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66
TargetType66.java:23:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Character)
TargetType66.java:24:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66
TargetType66.java:24:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Character)
3 errors
8 errors

View file

@ -197,7 +197,7 @@ public class StructuralMostSpecificTest
"class Test {\n" +
" void m(SAM1 s) { }\n" +
" void m(SAM2 s) { }\n" +
" { m(x->{ #LR }); }\n" +
" { m((#A1 x)->{ #LR }); }\n" +
"}\n";
String source;
@ -236,14 +236,17 @@ public class StructuralMostSpecificTest
void check() {
checkCount.incrementAndGet();
if (ak1 != ak2)
return;
if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2))
return;
if (lrk.needsConversion(rt1) != lrk.needsConversion(rt2))
return;
boolean m1MoreSpecific = moreSpecific(rt1, rt2, ek1, ek2, ak1, ak2);
boolean m2MoreSpecific = moreSpecific(rt2, rt1, ek2, ek1, ak2, ak1);
boolean m1MoreSpecific = rt1.moreSpecificThan(rt2);
boolean m2MoreSpecific = rt2.moreSpecificThan(rt1);
boolean ambiguous = (m1MoreSpecific == m2MoreSpecific);
@ -268,17 +271,6 @@ public class StructuralMostSpecificTest
}
}
boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1,
ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) {
if (!rk1.moreSpecificThan(rk2))
return false;
if (ak1 != ak2)
return false;
return true;
}
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {

View file

@ -1,122 +0,0 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8003280
* @summary Add lambda tests
* This test is for overloaded methods, verify that the specific method is
selected when type inference occurs
* @compile InferenceTest5.java
* @run main InferenceTest5
*/
import java.util.List;
import java.io.File;
public class InferenceTest5 {
private static void assertTrue(boolean b) {
if(!b)
throw new AssertionError();
}
public static void main(String[] args) {
InferenceTest5 test = new InferenceTest5();
int n = test.method1((a, b) -> {} );
assertTrue(n == 1);
n = test.method1(() -> null);
assertTrue(n == 2);
n = test.method1(a -> null);
assertTrue(n == 3);
n = test.method1(a -> {});
assertTrue(n == 4);
n = test.method1(() -> {});
assertTrue(n == 5);
n = test.method1((a, b) -> 0);
assertTrue(n == 6);
n = test.method1((a, b) -> null);
assertTrue(n == 6);
n = test.method1((a, b) -> null, (a, b) -> null);
assertTrue(n == 7);
}
int method1(SAM1<String> s) {
return 1;
}
int method1(SAM2 s) {
return 2;
}
int method1(SAM3 s) {
return 3;
}
int method1(SAM4 s) {
return 4;
}
int method1(SAM5 s) {
return 5;
}
int method1(SAM6<?, ? super Integer> s) {
return 6;
}
int method1(SAM6<?, ?>... s) {
return 7;
}
static interface SAM1<T> {
void foo(List<T> a, List<T> b);
}
static interface SAM2 {
List<String> foo();
}
static interface SAM3 {
String foo(int a);
}
static interface SAM4 {
void foo(List<File> a);
}
static interface SAM5 {
void foo();
}
static interface SAM6<T, V> {
V get(T t, T t2);
}
}

View file

@ -1,16 +1,16 @@
/*
* @test /nodynamiccopyright/
* @bug 8003280
* @bug 8003280 8016177
* @summary Add lambda tests
* Missing cast to SAM type that causes type inference to not work.
* @compile/fail/ref=InferenceTest_neg5.out -XDrawDiagnostics InferenceTest_neg5.java
* @compile -XDrawDiagnostics InferenceTest6.java
*/
import java.util.*;
public class InferenceTest_neg5 {
public class InferenceTest6 {
public static void main(String[] args) {
InferenceTest_neg5 test = new InferenceTest_neg5();
InferenceTest6 test = new InferenceTest6();
test.method1(n -> {});
test.method1((SAM1<String>)n -> {});
test.method1((SAM1<Integer>)n -> {n++;});

View file

@ -1,4 +1,5 @@
InferenceTest_neg1_2.java:14:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM4<java.lang.Double,java.lang.String>), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM5<java.lang.Integer>), InferenceTest_neg1_2
InferenceTest_neg1_2.java:15:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM2), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM4<java.lang.Double,java.lang.String>), InferenceTest_neg1_2
InferenceTest_neg1_2.java:16:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM3<java.lang.Integer>), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM5<java.lang.Integer>), InferenceTest_neg1_2
3 errors
InferenceTest_neg1_2.java:15:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM4<java.lang.Double,java.lang.String>), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM5<java.lang.Integer>), InferenceTest_neg1_2
InferenceTest_neg1_2.java:16:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM4<java.lang.Double,java.lang.String>), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM5<java.lang.Integer>), InferenceTest_neg1_2
InferenceTest_neg1_2.java:16:20: compiler.err.cant.apply.symbol: kindname.method, method, InferenceTest_neg1_2.SAM4<java.lang.Double,java.lang.String>, @597, kindname.class, InferenceTest_neg1_2, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, java.lang.String)))
4 errors

View file

@ -1,2 +0,0 @@
InferenceTest_neg5.java:14:21: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: X)
1 error

View file

@ -227,12 +227,7 @@ public class TypeInferenceComboTest
}
else if (lambdaBodyType != LambdaBody.RETURN_ARG)
return false;
if ( genericDeclKind == GenericDeclKind.GENERIC_NOBOUND ||
genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
if ( parameterType == TypeKind.GENERIC &&
parameterKind == ParameterKind.IMPLICIT) //cyclic inference
return false;
}
return true;
}