8029718: Should always use lambda body structure to disambiguate overload resolution
Reviewed-by: dlsmith, jjg, jlahoda
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Apr 21 22:51:49 2014 +0100
@@ -2616,7 +2616,7 @@
* - 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) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Mon Apr 21 22:51:49 2014 +0100
@@ -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.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.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 @@
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 @@
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 @@
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 @@
}
}
//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 @@
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 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 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 @@
}
}
}
+
+ /* 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 @@
/**
* handler that is executed when a node has been discarded
*/
- abstract void skip(JCTree tree);
+ void skip(JCTree tree) {}
}
/**
@@ -779,11 +911,6 @@
PolyScanner() {
super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE));
}
-
- @Override
- void skip(JCTree tree) {
- //do nothing
- }
}
/**
@@ -796,11 +923,6 @@
super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
FORLOOP, RETURN, SYNCHRONIZED, SWITCH, TRY, WHILELOOP));
}
-
- @Override
- void skip(JCTree tree) {
- //do nothing
- }
}
/**
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Mon Apr 21 22:51:49 2014 +0100
@@ -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.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
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Mon Apr 21 22:51:49 2014 +0100
@@ -2359,6 +2359,7 @@
/** 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;
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Apr 21 22:51:49 2014 +0100
@@ -738,6 +738,9 @@
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
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Mon Apr 21 22:51:49 2014 +0100
@@ -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 @@
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
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/LambdaBodyNeitherValueNorVoidCompatible.java Mon Apr 21 22:51:49 2014 +0100
@@ -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;
+ }
+ });
+ }
+}
--- a/langtools/test/tools/javac/lambda/ErroneousLambdaExpr.java Fri Apr 18 17:25:43 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * 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
- * 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
- * stale state after speculative attribution round leads to missing classfiles
- * @compile/fail/ref=ErroneousLambdaExpr.out -XDrawDiagnostics ErroneousLambdaExpr.java
- */
-public class ErroneousLambdaExpr<T> {
-
- static int assertionCount = 0;
-
- static void assertTrue(boolean cond) {
- assertionCount++;
- if (!cond)
- throw new AssertionError();
- }
-
- interface SAM1<X> {
- X m(X t, String s);
- }
-
- interface SAM2 {
- void m(String s, int i);
- }
-
- interface SAM3<X> {
- X m(X t, String s, int i);
- }
-
- void call(SAM1<T> s1) { assertTrue(true); }
-
- void call(SAM2 s2) { assertTrue(false); }
-
- void call(SAM3<T> s3) { assertTrue(false); }
-
- public static void main(String[] args) {
- ErroneousLambdaExpr<StringBuilder> test =
- new ErroneousLambdaExpr<>();
-
- test.call((builder, string) -> { builder.append(string); return builder; });
- assertTrue(assertionCount == 1);
- }
-}
--- a/langtools/test/tools/javac/lambda/ErroneousLambdaExpr.out Fri Apr 18 17:25:43 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/LambdaExprLeadsToMissingClassFilesTest.java Mon Apr 21 22:51:49 2014 +0100
@@ -0,0 +1,66 @@
+/*
+ * 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
+ * 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
+ * stale state after speculative attribution round leads to missing classfiles
+ */
+public class LambdaExprLeadsToMissingClassFilesTest<T> {
+
+ static int assertionCount = 0;
+
+ static void assertTrue(boolean cond) {
+ assertionCount++;
+ if (!cond) {
+ throw new AssertionError();
+ }
+ }
+
+ interface SAM1<X> {
+ X m(X t, String s);
+ }
+
+ interface SAM2 {
+ void m(String s, int i);
+ }
+
+ interface SAM3<X> {
+ X m(X t, String s, int i);
+ }
+
+ void call(SAM1<T> s1) { assertTrue(true); }
+
+ void call(SAM2 s2) { assertTrue(false); }
+
+ void call(SAM3<T> s3) { assertTrue(false); }
+
+ public static void main(String[] args) {
+ LambdaExprLeadsToMissingClassFilesTest<StringBuilder> test =
+ new LambdaExprLeadsToMissingClassFilesTest<>();
+
+ test.call((builder, string) -> { builder.append(string); return builder; });
+ assertTrue(assertionCount == 1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific09.java Mon Apr 21 22:51:49 2014 +0100
@@ -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 "";
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific09.out Mon Apr 21 22:51:49 2014 +0100
@@ -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
--- a/langtools/test/tools/javac/lambda/TargetType01.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/test/tools/javac/lambda/TargetType01.java Mon Apr 21 22:51:49 2014 +0100
@@ -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 @@
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
}
}
--- a/langtools/test/tools/javac/lambda/TargetType01.out Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/test/tools/javac/lambda/TargetType01.out Mon Apr 21 22:51:49 2014 +0100
@@ -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
--- a/langtools/test/tools/javac/lambda/TargetType02.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/test/tools/javac/lambda/TargetType02.java Mon Apr 21 22:51:49 2014 +0100
@@ -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 @@
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;
+ });
+ });
}
}
--- a/langtools/test/tools/javac/lambda/TargetType02.out Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/test/tools/javac/lambda/TargetType02.out Mon Apr 21 22:51:49 2014 +0100
@@ -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
--- a/langtools/test/tools/javac/lambda/TargetType21.out Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/test/tools/javac/lambda/TargetType21.out Mon Apr 21 22:51:49 2014 +0100
@@ -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
--- a/langtools/test/tools/javac/lambda/TargetType42.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/test/tools/javac/lambda/TargetType42.java Mon Apr 21 22:51:49 2014 +0100
@@ -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);
}
}
--- a/langtools/test/tools/javac/lambda/lambdaExpression/LambdaTest1.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/test/tools/javac/lambda/lambdaExpression/LambdaTest1.java Mon Apr 21 22:51:49 2014 +0100
@@ -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 {
--- a/langtools/test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java Fri Apr 18 17:25:43 2014 -0700
+++ b/langtools/test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java Mon Apr 21 22:51:49 2014 +0100
@@ -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 @@
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);
}