mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-11 19:08:23 +00:00
8029718: Should always use lambda body structure to disambiguate overload resolution
Reviewed-by: dlsmith, jjg, jlahoda
This commit is contained in:
parent
04e1109b69
commit
a50db59b59
@ -2616,7 +2616,7 @@ public class Attr extends JCTree.Visitor {
|
||||
* - an instance field, we use the first constructor.
|
||||
* - a static field, we create a fake clinit method.
|
||||
*/
|
||||
private Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) {
|
||||
public Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) {
|
||||
Env<AttrContext> lambdaEnv;
|
||||
Symbol owner = env.info.scope.owner;
|
||||
if (owner.kind == VAR && owner.owner.kind == TYP) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2014, 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
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
package com.sun.tools.javac.comp;
|
||||
|
||||
import com.sun.source.tree.MemberReferenceTree;
|
||||
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.tree.*;
|
||||
import com.sun.tools.javac.util.*;
|
||||
@ -35,10 +35,8 @@ import com.sun.tools.javac.code.Type.*;
|
||||
import com.sun.tools.javac.comp.Attr.ResultInfo;
|
||||
import com.sun.tools.javac.comp.Infer.InferenceContext;
|
||||
import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
|
||||
import com.sun.tools.javac.comp.Resolve.ReferenceLookupHelper;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
@ -48,6 +46,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import static com.sun.tools.javac.code.Kinds.VAL;
|
||||
import static com.sun.tools.javac.code.TypeTag.*;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
|
||||
@ -75,6 +74,8 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
final Symtab syms;
|
||||
final TreeMaker make;
|
||||
final Types types;
|
||||
final Flow flow;
|
||||
final Names names;
|
||||
|
||||
public static DeferredAttr instance(Context context) {
|
||||
DeferredAttr instance = context.get(deferredAttrKey);
|
||||
@ -95,7 +96,8 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
syms = Symtab.instance(context);
|
||||
make = TreeMaker.instance(context);
|
||||
types = Types.instance(context);
|
||||
Names names = Names.instance(context);
|
||||
flow = Flow.instance(context);
|
||||
names = Names.instance(context);
|
||||
stuckTree = make.Ident(names.empty).setType(Type.stuckType);
|
||||
emptyDeferredAttrContext =
|
||||
new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
|
||||
@ -138,6 +140,11 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
return DEFERRED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeferredType";
|
||||
}
|
||||
|
||||
/**
|
||||
* A speculative cache is used to keep track of all overload resolution rounds
|
||||
* that triggered speculative attribution on a given deferred type. Each entry
|
||||
@ -376,7 +383,9 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
//where
|
||||
protected TreeScanner unenterScanner = new TreeScanner() {
|
||||
protected UnenterScanner unenterScanner = new UnenterScanner();
|
||||
|
||||
class UnenterScanner extends TreeScanner {
|
||||
@Override
|
||||
public void visitClassDef(JCClassDecl tree) {
|
||||
ClassSymbol csym = tree.sym;
|
||||
@ -389,7 +398,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
syms.classes.remove(csym.flatname);
|
||||
super.visitClassDef(tree);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A deferred context is created on each method check. A deferred context is
|
||||
@ -593,19 +602,111 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
public void visitLambda(JCLambda tree) {
|
||||
Check.CheckContext checkContext = resultInfo.checkContext;
|
||||
Type pt = resultInfo.pt;
|
||||
if (inferenceContext.inferencevars.contains(pt)) {
|
||||
//ok
|
||||
return;
|
||||
} else {
|
||||
if (!inferenceContext.inferencevars.contains(pt)) {
|
||||
//must be a functional descriptor
|
||||
Type descriptorType = null;
|
||||
try {
|
||||
Type desc = types.findDescriptorType(pt);
|
||||
if (desc.getParameterTypes().length() != tree.params.length()) {
|
||||
checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
|
||||
}
|
||||
descriptorType = types.findDescriptorType(pt);
|
||||
} catch (Types.FunctionDescriptorLookupError ex) {
|
||||
checkContext.report(null, ex.getDiagnostic());
|
||||
}
|
||||
|
||||
if (descriptorType.getParameterTypes().length() != tree.params.length()) {
|
||||
checkContext.report(tree,
|
||||
diags.fragment("incompatible.arg.types.in.lambda"));
|
||||
}
|
||||
|
||||
Type currentReturnType = descriptorType.getReturnType();
|
||||
boolean returnTypeIsVoid = currentReturnType.hasTag(VOID);
|
||||
if (tree.getBodyKind() == BodyKind.EXPRESSION) {
|
||||
boolean isExpressionCompatible = !returnTypeIsVoid ||
|
||||
TreeInfo.isExpressionStatement((JCExpression)tree.getBody());
|
||||
if (!isExpressionCompatible) {
|
||||
resultInfo.checkContext.report(tree.pos(),
|
||||
diags.fragment("incompatible.ret.type.in.lambda",
|
||||
diags.fragment("missing.ret.val", currentReturnType)));
|
||||
}
|
||||
} else {
|
||||
LambdaBodyStructChecker lambdaBodyChecker =
|
||||
new LambdaBodyStructChecker();
|
||||
|
||||
tree.body.accept(lambdaBodyChecker);
|
||||
boolean isVoidCompatible = lambdaBodyChecker.isVoidCompatible;
|
||||
|
||||
if (returnTypeIsVoid) {
|
||||
if (!isVoidCompatible) {
|
||||
resultInfo.checkContext.report(tree.pos(),
|
||||
diags.fragment("unexpected.ret.val"));
|
||||
}
|
||||
} else {
|
||||
boolean isValueCompatible = lambdaBodyChecker.isPotentiallyValueCompatible
|
||||
&& !canLambdaBodyCompleteNormally(tree);
|
||||
if (!isValueCompatible && !isVoidCompatible) {
|
||||
log.error(tree.body.pos(),
|
||||
"lambda.body.neither.value.nor.void.compatible");
|
||||
}
|
||||
|
||||
if (!isValueCompatible) {
|
||||
resultInfo.checkContext.report(tree.pos(),
|
||||
diags.fragment("incompatible.ret.type.in.lambda",
|
||||
diags.fragment("missing.ret.val", currentReturnType)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean canLambdaBodyCompleteNormally(JCLambda tree) {
|
||||
JCLambda newTree = new TreeCopier<>(make).copy(tree);
|
||||
/* attr.lambdaEnv will create a meaningful env for the
|
||||
* lambda expression. This is specially useful when the
|
||||
* lambda is used as the init of a field. But we need to
|
||||
* remove any added symbol.
|
||||
*/
|
||||
Env<AttrContext> localEnv = attr.lambdaEnv(newTree, env);
|
||||
try {
|
||||
List<JCVariableDecl> tmpParams = newTree.params;
|
||||
while (tmpParams.nonEmpty()) {
|
||||
tmpParams.head.vartype = make.at(tmpParams.head).Type(syms.errType);
|
||||
tmpParams = tmpParams.tail;
|
||||
}
|
||||
|
||||
attr.attribStats(newTree.params, localEnv);
|
||||
|
||||
/* set pt to Type.noType to avoid generating any bound
|
||||
* which may happen if lambda's return type is an
|
||||
* inference variable
|
||||
*/
|
||||
Attr.ResultInfo bodyResultInfo = attr.new ResultInfo(VAL, Type.noType);
|
||||
localEnv.info.returnResult = bodyResultInfo;
|
||||
|
||||
// discard any log output
|
||||
Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
|
||||
try {
|
||||
JCBlock body = (JCBlock)newTree.body;
|
||||
/* we need to attribute the lambda body before
|
||||
* doing the aliveness analysis. This is because
|
||||
* constant folding occurs during attribution
|
||||
* and the reachability of some statements depends
|
||||
* on constant values, for example:
|
||||
*
|
||||
* while (true) {...}
|
||||
*/
|
||||
attr.attribStats(body.stats, localEnv);
|
||||
|
||||
attr.preFlow(newTree);
|
||||
/* make an aliveness / reachability analysis of the lambda
|
||||
* to determine if it can complete normally
|
||||
*/
|
||||
flow.analyzeLambda(localEnv, newTree, make, true);
|
||||
} finally {
|
||||
log.popDiagnosticHandler(diagHandler);
|
||||
}
|
||||
return newTree.canCompleteNormally;
|
||||
} finally {
|
||||
JCBlock body = (JCBlock)newTree.body;
|
||||
unenterScanner.scan(body.stats);
|
||||
localEnv.info.scope.leave();
|
||||
}
|
||||
}
|
||||
|
||||
@ -623,10 +724,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
public void visitReference(JCMemberReference tree) {
|
||||
Check.CheckContext checkContext = resultInfo.checkContext;
|
||||
Type pt = resultInfo.pt;
|
||||
if (inferenceContext.inferencevars.contains(pt)) {
|
||||
//ok
|
||||
return;
|
||||
} else {
|
||||
if (!inferenceContext.inferencevars.contains(pt)) {
|
||||
try {
|
||||
types.findDescriptorType(pt);
|
||||
} catch (Types.FunctionDescriptorLookupError ex) {
|
||||
@ -656,6 +754,40 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This visitor looks for return statements, its analysis will determine if
|
||||
* a lambda body is void or value compatible. We must analyze return
|
||||
* statements contained in the lambda body only, thus any return statement
|
||||
* contained in an inner class or inner lambda body, should be ignored.
|
||||
*/
|
||||
class LambdaBodyStructChecker extends TreeScanner {
|
||||
boolean isVoidCompatible = true;
|
||||
boolean isPotentiallyValueCompatible = true;
|
||||
|
||||
@Override
|
||||
public void visitClassDef(JCClassDecl tree) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLambda(JCLambda tree) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewClass(JCNewClass tree) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReturn(JCReturn tree) {
|
||||
if (tree.expr != null) {
|
||||
isVoidCompatible = false;
|
||||
} else {
|
||||
isPotentiallyValueCompatible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** an empty deferred attribution context - all methods throw exceptions */
|
||||
@ -767,7 +899,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
/**
|
||||
* handler that is executed when a node has been discarded
|
||||
*/
|
||||
abstract void skip(JCTree tree);
|
||||
void skip(JCTree tree) {}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -779,11 +911,6 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
PolyScanner() {
|
||||
super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE));
|
||||
}
|
||||
|
||||
@Override
|
||||
void skip(JCTree tree) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -796,11 +923,6 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
|
||||
FORLOOP, RETURN, SYNCHRONIZED, SWITCH, TRY, WHILELOOP));
|
||||
}
|
||||
|
||||
@Override
|
||||
void skip(JCTree tree) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2014, 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
|
||||
@ -45,7 +45,7 @@ import static com.sun.tools.javac.code.TypeTag.VOID;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
|
||||
/** This pass implements dataflow analysis for Java programs though
|
||||
* different AST visitor steps. Liveness analysis (see AliveAlanyzer) checks that
|
||||
* different AST visitor steps. Liveness analysis (see AliveAnalyzer) checks that
|
||||
* every statement is reachable. Exception analysis (see FlowAnalyzer) ensures that
|
||||
* every checked exception that is thrown is declared or caught. Definite assignment analysis
|
||||
* (see AssignAnalyzer) ensures that each variable is assigned when used. Definite
|
||||
|
||||
@ -2359,6 +2359,7 @@ public class Lower extends TreeTranslator {
|
||||
/** Visitor method: Translate a single node.
|
||||
* Attach the source position from the old tree to its replacement tree.
|
||||
*/
|
||||
@Override
|
||||
public <T extends JCTree> T translate(T tree) {
|
||||
if (tree == null) {
|
||||
return null;
|
||||
|
||||
@ -738,6 +738,9 @@ compiler.misc.incompatible.ret.type.in.mref=\
|
||||
bad return type in method reference\n\
|
||||
{0}
|
||||
|
||||
compiler.err.lambda.body.neither.value.nor.void.compatible=\
|
||||
lambda body is neither value nor void compatible
|
||||
|
||||
# 0: list of type
|
||||
compiler.err.incompatible.thrown.types.in.mref=\
|
||||
incompatible thrown types {0} in method reference
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2014, 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
|
||||
@ -56,9 +56,9 @@ public class TreeTranslator extends JCTree.Visitor {
|
||||
return null;
|
||||
} else {
|
||||
tree.accept(this);
|
||||
JCTree result = this.result;
|
||||
JCTree tmpResult = this.result;
|
||||
this.result = null;
|
||||
return (T)result; // XXX cast
|
||||
return (T)tmpResult; // XXX cast
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.
|
||||
*/
|
||||
|
||||
// key: compiler.err.lambda.body.neither.value.nor.void.compatible
|
||||
// key: compiler.err.cant.apply.symbol
|
||||
// key: compiler.misc.incompatible.ret.type.in.lambda
|
||||
// key: compiler.misc.missing.ret.val
|
||||
// key: compiler.misc.no.conforming.assignment.exists
|
||||
|
||||
class LambdaBodyNeitherValueNorVoidCompatible {
|
||||
interface I {
|
||||
String f(String x);
|
||||
}
|
||||
|
||||
static void foo(I i) {}
|
||||
|
||||
void m() {
|
||||
foo((x) -> {
|
||||
if (x == null) {
|
||||
return;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
ErroneousLambdaExpr.java:63:13: compiler.err.ref.ambiguous: call, kindname.method, call(ErroneousLambdaExpr.SAM1<T>), ErroneousLambdaExpr, kindname.method, call(ErroneousLambdaExpr.SAM2), ErroneousLambdaExpr
|
||||
1 error
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2014 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,16 +26,16 @@
|
||||
* @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> {
|
||||
public class LambdaExprLeadsToMissingClassFilesTest<T> {
|
||||
|
||||
static int assertionCount = 0;
|
||||
|
||||
static void assertTrue(boolean cond) {
|
||||
assertionCount++;
|
||||
if (!cond)
|
||||
if (!cond) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
interface SAM1<X> {
|
||||
@ -57,8 +57,8 @@ public class ErroneousLambdaExpr<T> {
|
||||
void call(SAM3<T> s3) { assertTrue(false); }
|
||||
|
||||
public static void main(String[] args) {
|
||||
ErroneousLambdaExpr<StringBuilder> test =
|
||||
new ErroneousLambdaExpr<>();
|
||||
LambdaExprLeadsToMissingClassFilesTest<StringBuilder> test =
|
||||
new LambdaExprLeadsToMissingClassFilesTest<>();
|
||||
|
||||
test.call((builder, string) -> { builder.append(string); return builder; });
|
||||
assertTrue(assertionCount == 1);
|
||||
81
langtools/test/tools/javac/lambda/MostSpecific09.java
Normal file
81
langtools/test/tools/javac/lambda/MostSpecific09.java
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8029718
|
||||
* @summary Should always use lambda body structure to disambiguate overload resolution
|
||||
* @compile/fail/ref=MostSpecific09.out -XDrawDiagnostics -XDshouldStopPolicy=ATTR -XDverboseResolution=applicable,success MostSpecific09.java
|
||||
*/
|
||||
|
||||
class MostSpecific09 {
|
||||
|
||||
interface I {
|
||||
String xoo(String x);
|
||||
}
|
||||
|
||||
interface J {
|
||||
void xoo(int x);
|
||||
}
|
||||
|
||||
static void foo(I i) {}
|
||||
static void foo(J j) {}
|
||||
|
||||
static void moo(I i) {}
|
||||
static void moo(J j) {}
|
||||
|
||||
void m() {
|
||||
foo((x) -> { return x += 1; });
|
||||
foo((x) -> { return ""; });
|
||||
foo((x) -> { System.out.println(""); });
|
||||
foo((x) -> { return ""; System.out.println(""); });
|
||||
foo((x) -> { throw new RuntimeException(); });
|
||||
foo((x) -> { while (true); });
|
||||
|
||||
foo((x) -> x += 1);
|
||||
foo((x) -> "");
|
||||
}
|
||||
|
||||
/* any return statement that is not in the body of the lambda but in an
|
||||
* inner class or another lambda should be ignored for value void compatibility
|
||||
* determination.
|
||||
*/
|
||||
void m1() {
|
||||
boolean cond = true;
|
||||
foo((x) -> {
|
||||
if (cond) {
|
||||
return "";
|
||||
}
|
||||
System.out.println("");
|
||||
});
|
||||
|
||||
foo((x)->{
|
||||
class Bar {
|
||||
String m() {
|
||||
return "from Bar.m()";
|
||||
}
|
||||
}
|
||||
class Boo {
|
||||
Bar b = new Bar (){
|
||||
String m() {
|
||||
return "from Bar$1.m()";
|
||||
}
|
||||
};
|
||||
}
|
||||
moo((y) -> { return ""; });
|
||||
return;
|
||||
});
|
||||
|
||||
foo((x)->{
|
||||
class Bar {
|
||||
void m() {}
|
||||
}
|
||||
class Boo {
|
||||
Bar b = new Bar (){
|
||||
void m() {
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
moo((y) -> { System.out.println(""); });
|
||||
return "";
|
||||
});
|
||||
}
|
||||
}
|
||||
27
langtools/test/tools/javac/lambda/MostSpecific09.out
Normal file
27
langtools/test/tools/javac/lambda/MostSpecific09.out
Normal file
@ -0,0 +1,27 @@
|
||||
MostSpecific09.java:25:9: compiler.note.verbose.resolve.multi: foo, MostSpecific09, 0, BASIC, compiler.misc.type.none, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, foo(MostSpecific09.I), null)}
|
||||
MostSpecific09.java:26:9: compiler.note.verbose.resolve.multi: foo, MostSpecific09, 0, BASIC, compiler.misc.type.none, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, foo(MostSpecific09.I), null)}
|
||||
MostSpecific09.java:27:9: compiler.note.verbose.resolve.multi: foo, MostSpecific09, 0, BASIC, compiler.misc.type.none, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, foo(MostSpecific09.J), null)}
|
||||
MostSpecific09.java:27:32: compiler.note.verbose.resolve.multi: println, java.io.PrintStream, 1, BASIC, java.lang.String, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, println(java.lang.Object), null),(compiler.misc.applicable.method.found: 1, println(java.lang.String), null)}
|
||||
MostSpecific09.java:28:13: compiler.err.lambda.body.neither.value.nor.void.compatible
|
||||
MostSpecific09.java:28:9: compiler.err.cant.apply.symbols: kindname.method, foo, @680,{(compiler.misc.inapplicable.method: kindname.method, MostSpecific09, foo(MostSpecific09.I), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.missing.ret.val: java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, MostSpecific09, foo(MostSpecific09.J), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.unexpected.ret.val)))}
|
||||
MostSpecific09.java:28:43: compiler.note.verbose.resolve.multi: println, java.io.PrintStream, 1, BASIC, java.lang.String, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, println(java.lang.Object), null),(compiler.misc.applicable.method.found: 1, println(java.lang.String), null)}
|
||||
MostSpecific09.java:29:9: compiler.err.ref.ambiguous: foo, kindname.method, foo(MostSpecific09.I), MostSpecific09, kindname.method, foo(MostSpecific09.J), MostSpecific09
|
||||
MostSpecific09.java:29:28: compiler.note.verbose.resolve.multi: <init>, java.lang.RuntimeException, 0, BASIC, compiler.misc.no.args, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, java.lang.RuntimeException(), null)}
|
||||
MostSpecific09.java:30:9: compiler.err.ref.ambiguous: foo, kindname.method, foo(MostSpecific09.I), MostSpecific09, kindname.method, foo(MostSpecific09.J), MostSpecific09
|
||||
MostSpecific09.java:32:9: compiler.err.ref.ambiguous: foo, kindname.method, foo(MostSpecific09.I), MostSpecific09, kindname.method, foo(MostSpecific09.J), MostSpecific09
|
||||
MostSpecific09.java:33:9: compiler.note.verbose.resolve.multi: foo, MostSpecific09, 0, BASIC, compiler.misc.type.none, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, foo(MostSpecific09.I), null)}
|
||||
MostSpecific09.java:42:13: compiler.err.lambda.body.neither.value.nor.void.compatible
|
||||
MostSpecific09.java:42:9: compiler.err.cant.apply.symbols: kindname.method, foo, @1129,{(compiler.misc.inapplicable.method: kindname.method, MostSpecific09, foo(MostSpecific09.I), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.missing.ret.val: java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, MostSpecific09, foo(MostSpecific09.J), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.unexpected.ret.val)))}
|
||||
MostSpecific09.java:46:23: compiler.note.verbose.resolve.multi: println, java.io.PrintStream, 1, BASIC, java.lang.String, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, println(java.lang.Object), null),(compiler.misc.applicable.method.found: 1, println(java.lang.String), null)}
|
||||
MostSpecific09.java:49:9: compiler.note.verbose.resolve.multi: foo, MostSpecific09, 0, BASIC, compiler.misc.type.none, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, foo(MostSpecific09.J), null)}
|
||||
MostSpecific09.java:56:25: compiler.note.verbose.resolve.multi: <init>, Bar, 0, BASIC, compiler.misc.no.args, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, Bar(), null)}
|
||||
MostSpecific09.java:56:35: compiler.note.verbose.resolve.multi: <init>, Bar, 0, BASIC, compiler.misc.no.args, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, Bar(), null)}
|
||||
MostSpecific09.java:56:25: compiler.note.verbose.resolve.multi: <init>, compiler.misc.anonymous.class: MostSpecific09$1Boo$1, 0, BASIC, compiler.misc.no.args, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, compiler.misc.anonymous.class: MostSpecific09$1Boo$1(), null)}
|
||||
MostSpecific09.java:62:13: compiler.note.verbose.resolve.multi: moo, MostSpecific09, 0, BASIC, compiler.misc.type.none, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, moo(MostSpecific09.I), null)}
|
||||
MostSpecific09.java:66:9: compiler.note.verbose.resolve.multi: foo, MostSpecific09, 0, BASIC, compiler.misc.type.none, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, foo(MostSpecific09.I), null)}
|
||||
MostSpecific09.java:71:25: compiler.note.verbose.resolve.multi: <init>, Bar, 0, BASIC, compiler.misc.no.args, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, Bar(), null)}
|
||||
MostSpecific09.java:71:35: compiler.note.verbose.resolve.multi: <init>, Bar, 0, BASIC, compiler.misc.no.args, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, Bar(), null)}
|
||||
MostSpecific09.java:71:25: compiler.note.verbose.resolve.multi: <init>, compiler.misc.anonymous.class: MostSpecific09$2Boo$1, 0, BASIC, compiler.misc.no.args, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, compiler.misc.anonymous.class: MostSpecific09$2Boo$1(), null)}
|
||||
MostSpecific09.java:77:13: compiler.note.verbose.resolve.multi: moo, MostSpecific09, 0, BASIC, compiler.misc.type.none, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, moo(MostSpecific09.J), null)}
|
||||
MostSpecific09.java:77:36: compiler.note.verbose.resolve.multi: println, java.io.PrintStream, 1, BASIC, java.lang.String, compiler.misc.no.args,{(compiler.misc.applicable.method.found: 0, println(java.lang.Object), null),(compiler.misc.applicable.method.found: 1, println(java.lang.String), null)}
|
||||
7 errors
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2014, 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
|
||||
@ -42,6 +42,10 @@ class TargetType01 {
|
||||
static String M(F_S_S f){ return null; }
|
||||
|
||||
static {
|
||||
M(x1 -> { return M( x2 -> { return x1 + x2; });}); //ambiguous
|
||||
M(x1 -> {
|
||||
return M( x2 -> {
|
||||
return x1 + x2;
|
||||
});
|
||||
}); //ambiguous
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +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
|
||||
TargetType01.java:46:20: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01
|
||||
2 errors
|
||||
|
||||
@ -1,31 +1,9 @@
|
||||
/*
|
||||
* 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
|
||||
* 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
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8003280 8029718
|
||||
* @summary Add lambda tests
|
||||
* check overload resolution and target type inference w.r.t. generic methods
|
||||
* Should always use lambda body structure to disambiguate overload resolution
|
||||
* @author Maurizio Cimadamore
|
||||
* @compile/fail/ref=TargetType02.out -XDrawDiagnostics TargetType02.java
|
||||
*/
|
||||
@ -47,9 +25,18 @@ public class TargetType02 {
|
||||
static <Z extends Number> void call3(S1<Z> s) { }
|
||||
static <Z extends String> void call3(S2<Z> s) { }
|
||||
|
||||
static <Z extends Number> Z call4(S1<Z> s) { return null; }
|
||||
static <Z extends String> Z call4(S2<Z> s) { return null; }
|
||||
|
||||
void test() {
|
||||
call1(i -> { toString(); return i; });
|
||||
call2(i -> { toString(); return i; });
|
||||
call3(i -> { toString(); return i; });
|
||||
call3(i -> {
|
||||
toString();
|
||||
return call4(j -> {
|
||||
return j;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
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
|
||||
TargetType02.java:33:14: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, java.lang.String)
|
||||
TargetType02.java:34:9: compiler.err.ref.ambiguous: call3, kindname.method, <Z>call3(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call3(TargetType02.S2<Z>), TargetType02
|
||||
TargetType02.java:35:9: compiler.err.ref.ambiguous: call3, kindname.method, <Z>call3(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call3(TargetType02.S2<Z>), TargetType02
|
||||
TargetType02.java:37:20: compiler.err.ref.ambiguous: call4, kindname.method, <Z>call4(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call4(TargetType02.S2<Z>), TargetType02
|
||||
4 errors
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
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: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
|
||||
TargetType21.java:32:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
|
||||
TargetType21.java:32:13: compiler.err.cant.apply.symbol: kindname.method, call, TargetType21.SAM1, @888, kindname.class, TargetType21, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))
|
||||
TargetType21.java:33:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, <R,A>call(TargetType21.SAM3<R,A>), TargetType21
|
||||
4 errors
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2014, 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
|
||||
@ -31,12 +31,18 @@
|
||||
class TargetType42 {
|
||||
|
||||
interface SAM<X, Y> {
|
||||
Y f(X x);
|
||||
Y f(X x);
|
||||
}
|
||||
|
||||
<Z> void m(SAM<String, SAM<Z, Object>> s, Z z) { }
|
||||
|
||||
void test(Object obj) {
|
||||
m((x)->{ class Foo { }; return (x2)-> { new Foo(); return null; }; }, obj);
|
||||
m((x)->{
|
||||
class Foo { }
|
||||
return (x2)-> {
|
||||
new Foo();
|
||||
return null;
|
||||
};
|
||||
}, obj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2014, 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
|
||||
@ -33,7 +33,6 @@
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
public class LambdaTest1 {
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2014, 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
|
||||
@ -209,7 +209,11 @@ public class SamConversionComboTest {
|
||||
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
|
||||
DiagnosticChecker dc = new DiagnosticChecker();
|
||||
JavacTask ct = (JavacTask)tool.getTask(null, null, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile));
|
||||
ct.analyze();
|
||||
try {
|
||||
ct.analyze();
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("failing SAM source file \n" + samSourceFile + "\n\n" + "failing client source file \n"+ clientSourceFile);
|
||||
}
|
||||
if (dc.errorFound == checkSamConversion()) {
|
||||
throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user