8009131: Overload: javac should discard methods that lead to errors in lambdas with implicit parameter types

Lambdas that have errors in their bodies should make enclosing overload resolution fail

Reviewed-by: jjg
This commit is contained in:
Maurizio Cimadamore 2013-04-08 15:57:10 +01:00
parent b4b6e4f82e
commit ea55015155
9 changed files with 106 additions and 16 deletions

View File

@ -2340,11 +2340,34 @@ public class Attr extends JCTree.Visitor {
new ResultInfo(VAL, lambdaType.getReturnType(), funcContext);
localEnv.info.returnResult = bodyResultInfo;
if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
attribTree(that.getBody(), localEnv, bodyResultInfo);
} else {
JCBlock body = (JCBlock)that.body;
attribStats(body.stats, localEnv);
Log.DeferredDiagnosticHandler lambdaDeferredHandler = new Log.DeferredDiagnosticHandler(log);
try {
if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
attribTree(that.getBody(), localEnv, bodyResultInfo);
} else {
JCBlock body = (JCBlock)that.body;
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)));
//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);

View File

@ -731,6 +731,11 @@ compiler.misc.incompatible.arg.types.in.lambda=\
compiler.misc.incompatible.arg.types.in.mref=\
incompatible parameter types in method reference
# 0: list of type
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

View File

@ -0,0 +1,38 @@
/*
* 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.
*/
// key: compiler.err.cant.apply.symbol
// key: compiler.misc.no.conforming.assignment.exists
// key: compiler.misc.bad.arg.types.in.lambda
class BadArgTypesInLambda {
interface SAM {
void m(Integer i);
}
void g(SAM s) { }
void test() {
g(x->{ String s = x; });
}
}

View File

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

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
@ -23,11 +23,10 @@
/*
* @test
* @bug 8003280
* @bug 8003280 8009131
* @summary Add lambda tests
* check nested case of overload resolution and lambda parameter inference
* @author Maurizio Cimadamore
* @compile/fail/ref=TargetType01.out -XDrawDiagnostics TargetType01.java
* @compile TargetType01.java
*/
class TargetType01 {

View File

@ -1,3 +0,0 @@
TargetType01.java:46:9: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01
TargetType01.java:46: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,4 @@
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)
4 errors
3 errors

View File

@ -0,0 +1,26 @@
/*
* @test /nodynamiccopyright/
* @bug 8009131
* @summary Overload: javac should discard methods that lead to errors in lambdas with implicit parameter types
* @compile/fail/ref=TargetType66.out -XDrawDiagnostics TargetType66.java
*/
class TargetType66 {
interface SAM1 {
void m(String s);
}
interface SAM2 {
void m(Integer s);
}
void g(SAM1 s1) { }
void g(SAM2 s2) { }
void test() {
g(x->{ String s = x; }); //g(SAM1)
g(x->{ Integer i = x; }); //g(SAM2)
g(x->{ Object o = x; }); //ambiguous
g(x->{ Character c = x; }); //error: inapplicable methods
g(x->{ Character c = ""; }); //error: incompatible types
}
}

View File

@ -0,0 +1,4 @@
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.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)))}
TargetType66.java:24:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Character)
3 errors