OpenJDK / jdk / jdk
changeset 38508:03c87ceca5fd
8153884: Expression lambda erroneously compatible with void-returning descriptor
Summary: Fix lambda compatibility check for void returning expressions
Reviewed-by: vromero
author | mcimadamore |
---|---|
date | Mon, 16 May 2016 13:05:42 +0100 |
parents | d48ba9db4b7d |
children | 01582f186579 |
files | langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties langtools/test/tools/javac/Diagnostics/compressed/T8012003b.out langtools/test/tools/javac/diags/examples/StatExprExpected.java langtools/test/tools/javac/lambda/8153884/T8153884.java langtools/test/tools/javac/lambda/8153884/T8153884.out langtools/test/tools/javac/lambda/LambdaExpr10.out langtools/test/tools/javac/lambda/LambdaExprNotVoid.out |
diffstat | 8 files changed, 76 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Mon May 16 12:03:41 2016 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Mon May 16 13:05:42 2016 +0100 @@ -2678,6 +2678,7 @@ class ExpressionLambdaReturnContext extends FunctionalReturnContext { JCExpression expr; + boolean expStmtExpected; ExpressionLambdaReturnContext(JCExpression expr, CheckContext enclosingContext) { super(enclosingContext); @@ -2685,10 +2686,23 @@ } @Override + public void report(DiagnosticPosition pos, JCDiagnostic details) { + if (expStmtExpected) { + enclosingContext.report(pos, diags.fragment(Fragments.StatExprExpected)); + } else { + super.report(pos, details); + } + } + + @Override public boolean compatible(Type found, Type req, Warner warn) { //a void return is compatible with an expression statement lambda - return TreeInfo.isExpressionStatement(expr) && req.hasTag(VOID) || - super.compatible(found, req, warn); + if (req.hasTag(VOID)) { + expStmtExpected = true; + return TreeInfo.isExpressionStatement(expr); + } else { + return super.compatible(found, req, warn); + } } }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Mon May 16 12:03:41 2016 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Mon May 16 13:05:42 2016 +0100 @@ -779,6 +779,10 @@ bad return type in lambda expression\n\ {0} +compiler.misc.stat.expr.expected=\ + lambda body is not compatible with a void functional interface\n\ + (consider using a block lambda body, or use a statement expression instead) + # 0: type compiler.misc.incompatible.ret.type.in.mref=\ bad return type in method reference\n\
--- a/langtools/test/tools/javac/Diagnostics/compressed/T8012003b.out Mon May 16 12:03:41 2016 +0100 +++ b/langtools/test/tools/javac/Diagnostics/compressed/T8012003b.out Mon May 16 13:05:42 2016 +0100 @@ -1,5 +1,5 @@ T8012003b.java:30:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, java.lang.String, compiler.misc.no.args, kindname.class, T8012003b, (compiler.misc.arg.length.mismatch))) -T8012003b.java:31:16: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, void)) +T8012003b.java:31:16: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) T8012003b.java:32:22: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.conditional.target.cant.be.void)) T8012003b.java:33:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.String))) T8012003b.java:34:12: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/examples/StatExprExpected.java Mon May 16 13:05:42 2016 +0100 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.prob.found.req +// key: compiler.misc.stat.expr.expected + +class StatExprExpected { + void test() { + Runnable r = () -> (foo()); + } + + int foo() { return 1; } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/8153884/T8153884.java Mon May 16 13:05:42 2016 +0100 @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8153884 + * @summary Expression lambda erroneously compatible with void-returning descriptor + * @compile/fail/ref=T8153884.out -XDrawDiagnostics T8153884.java + */ + +class T8153884 { + void test() { + Runnable r = () -> (foo()); + } + + void foo() { } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/8153884/T8153884.out Mon May 16 13:05:42 2016 +0100 @@ -0,0 +1,2 @@ +T8153884.java:10:32: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) +1 error
--- a/langtools/test/tools/javac/lambda/LambdaExpr10.out Mon May 16 12:03:41 2016 +0100 +++ b/langtools/test/tools/javac/lambda/LambdaExpr10.out Mon May 16 13:05:42 2016 +0100 @@ -4,6 +4,6 @@ LambdaExpr10.java:24:46: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) LambdaExpr10.java:28:29: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) LambdaExpr10.java:29:33: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) -LambdaExpr10.java:33:35: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void)) -LambdaExpr10.java:34:49: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void)) +LambdaExpr10.java:33:35: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) +LambdaExpr10.java:34:49: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) 8 errors
--- a/langtools/test/tools/javac/lambda/LambdaExprNotVoid.out Mon May 16 12:03:41 2016 +0100 +++ b/langtools/test/tools/javac/lambda/LambdaExprNotVoid.out Mon May 16 13:05:42 2016 +0100 @@ -1,3 +1,3 @@ -LambdaExprNotVoid.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, void)) -LambdaExprNotVoid.java:15:21: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, void)) +LambdaExprNotVoid.java:14:21: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) +LambdaExprNotVoid.java:15:21: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected) 2 errors