changeset 47313:bc55f69eed06 lvti

Enhancement: add support for 'var' in implicit lambda parameters
author mcimadamore
date Wed, 27 Sep 2017 12:57:41 +0100
parents 06793e20e62a
children 89ff56cf0a2d
files src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties test/langtools/tools/javac/lambda/LambdaParserTest.java test/langtools/tools/javac/lvti/ParserTest.java test/langtools/tools/javac/lvti/ParserTest.out test/tools/javac/diags/examples/VarNotAllowedExplicitLambda.java
diffstat 6 files changed, 104 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Tue Sep 26 15:24:57 2017 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Sep 27 12:57:41 2017 +0100
@@ -3917,6 +3917,14 @@
             setErrorEndPos(token.pos);
             reportSyntaxError(S.prevToken().endPos, "expected3", COMMA, RPAREN, LBRACKET);
         }
+        if (lambdaParameters && allowLocalVariableTypeInference) {
+            List<JCVariableDecl> implicitParams = params.stream()
+                    .filter(p -> p.vartype == null)
+                    .collect(List.collector());
+            if (implicitParams.nonEmpty() && implicitParams.size() != params.size()) {
+                error(implicitParams.head, "var.not.allowed.explicit.lambda");
+            }
+        }
         return params.toList();
     }
 
@@ -4027,7 +4035,7 @@
         // need to distinguish between vararg annos and array annos
         // look at typeAnnotationsPushedBack comment
         this.permitTypeAnnotationsPushBack = true;
-        JCExpression type = parseType();
+        JCExpression type = parseType(lambdaParameter);
         this.permitTypeAnnotationsPushBack = false;
 
         if (token.kind == ELLIPSIS) {
@@ -4045,6 +4053,10 @@
             }
             typeAnnotationsPushedBack = List.nil();
         }
+        if (lambdaParameter && isRestrictedLocalVarTypeName(type)) {
+            //implicit lambda parameter type (with 'var')
+            type = null;
+        }
         return variableDeclaratorId(mods, type, lambdaParameter);
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Tue Sep 26 15:24:57 2017 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Sep 27 12:57:41 2017 +0100
@@ -1213,6 +1213,9 @@
 compiler.err.var.not.allowed.compound=\
     ''var'' is not allowed in a compound declaration
 
+compiler.err.var.not.allowed.explicit.lambda=\
+    ''var'' is not allowed in an explicitly-typed lambda expression
+
 compiler.misc.local.cant.infer.null=\
     variable initializer is ''null''
 
--- a/test/langtools/tools/javac/lambda/LambdaParserTest.java	Tue Sep 26 15:24:57 2017 +0200
+++ b/test/langtools/tools/javac/lambda/LambdaParserTest.java	Wed Sep 27 12:57:41 2017 +0100
@@ -40,6 +40,7 @@
  */
 
 import java.io.IOException;
+import java.util.Arrays;
 
 import combo.ComboInstance;
 import combo.ComboParameter;
@@ -105,26 +106,44 @@
         }
     }
 
+    enum SourceKind {
+        SOURCE_9("9"),
+        SOURCE_10("10");
+
+        String sourceNumber;
+
+        SourceKind(String sourceNumber) {
+            this.sourceNumber = sourceNumber;
+        }
+    }
+
     enum LambdaParameterKind implements ComboParameter {
-        IMPLICIT(""),
-        EXPLIICT_SIMPLE("A"),
-        EXPLIICT_SIMPLE_ARR1("A[]"),
-        EXPLIICT_SIMPLE_ARR2("A[][]"),
-        EXPLICIT_VARARGS("A..."),
-        EXPLICIT_GENERIC1("A<X>"),
-        EXPLICIT_GENERIC2("A<? extends X, ? super Y>"),
-        EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>..."),
-        EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]"),
-        EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]");
+
+        IMPLICIT_1("", ExplicitKind.IMPLICIT),
+        IMPLICIT_2("var", ExplicitKind.IMPLICIT_VAR),
+        EXPLIICT_SIMPLE("A", ExplicitKind.EXPLICIT),
+        EXPLIICT_SIMPLE_ARR1("A[]", ExplicitKind.EXPLICIT),
+        EXPLIICT_SIMPLE_ARR2("A[][]", ExplicitKind.EXPLICIT),
+        EXPLICIT_VARARGS("A...", ExplicitKind.EXPLICIT),
+        EXPLICIT_GENERIC1("A<X>", ExplicitKind.EXPLICIT),
+        EXPLICIT_GENERIC2("A<? extends X, ? super Y>", ExplicitKind.EXPLICIT),
+        EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>...", ExplicitKind.EXPLICIT),
+        EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]", ExplicitKind.EXPLICIT),
+        EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]", ExplicitKind.EXPLICIT);
+
+        enum ExplicitKind {
+            IMPLICIT,
+            IMPLICIT_VAR,
+            EXPLICIT;
+        }
 
         String parameterType;
+        ExplicitKind explicitKind;
 
-        LambdaParameterKind(String parameterType) {
+
+        LambdaParameterKind(String parameterType, ExplicitKind ekind) {
             this.parameterType = parameterType;
-        }
-
-        boolean explicit() {
-            return this != IMPLICIT;
+            this.explicitKind = ekind;
         }
 
         boolean isVarargs() {
@@ -136,12 +155,23 @@
         public String expand(String optParameter) {
             return parameterType;
         }
+
+        ExplicitKind explicitKind(SourceKind sk) {
+            switch (explicitKind) {
+                case IMPLICIT_VAR:
+                    return (sk == SourceKind.SOURCE_9) ?
+                            ExplicitKind.EXPLICIT : ExplicitKind.IMPLICIT_VAR;
+                default:
+                    return explicitKind;
+            }
+        }
     }
 
     enum ModifierKind implements ComboParameter {
         NONE(""),
         FINAL("final"),
-        PUBLIC("public");
+        PUBLIC("public"),
+        ANNO("@A");
 
         String modifier;
 
@@ -152,7 +182,8 @@
         boolean compatibleWith(LambdaParameterKind pk) {
             switch (this) {
                 case PUBLIC: return false;
-                case FINAL: return pk != LambdaParameterKind.IMPLICIT;
+                case ANNO:
+                case FINAL: return pk != LambdaParameterKind.IMPLICIT_1;
                 case NONE: return true;
                 default: throw new AssertionError("Invalid modifier kind " + this);
             }
@@ -208,6 +239,7 @@
         new ComboTestHelper<LambdaParserTest>()
                 .withFilter(LambdaParserTest::redundantTestFilter)
                 .withFilter(LambdaParserTest::badImplicitFilter)
+                .withDimension("SOURCE", (x, sk) -> x.sk = sk, SourceKind.values())
                 .withDimension("LAMBDA", (x, lk) -> x.lk = lk, LambdaKind.values())
                 .withDimension("NAME", (x, name) -> x.pn = name, LambdaParameterName.values())
                 .withArrayDimension("TYPE", (x, type, idx) -> x.pks[idx] = type, 2, LambdaParameterKind.values())
@@ -221,6 +253,7 @@
     ModifierKind[] mks = new ModifierKind[2];
     LambdaKind lk;
     LambdaParameterName pn;
+    SourceKind sk;
 
     boolean badImplicitFilter() {
         return !(mks[0] != ModifierKind.NONE && lk.isShort());
@@ -240,13 +273,15 @@
         return true;
     }
 
-    String template = "class Test {\n" +
-                      "   SAM s = #{EXPR};\n" +
-                      "}";
+    String template = "@interface A { }\n" +
+            "class Test {\n" +
+            "   SAM s = #{EXPR};\n" +
+            "}";
 
     @Override
     public void doWork() throws IOException {
         check(newCompilationTask()
+                .withOptions(Arrays.asList("-source", sk.sourceNumber))
                 .withSourceFromTemplate(template)
                 .parse());
     }
@@ -256,7 +291,7 @@
                 (lk.arity() > 1 && !mks[1].compatibleWith(pks[1]));
 
         if (lk.arity() == 2 &&
-                (pks[0].explicit() != pks[1].explicit() ||
+                (pks[0].explicitKind(sk) != pks[1].explicitKind(sk) ||
                 pks[0].isVarargs())) {
             errorExpected = true;
         }
--- a/test/langtools/tools/javac/lvti/ParserTest.java	Tue Sep 26 15:24:57 2017 +0200
+++ b/test/langtools/tools/javac/lvti/ParserTest.java	Wed Sep 27 12:57:41 2017 +0100
@@ -60,7 +60,7 @@
         List<? extends var> l2; //error
         List<? super var> l3; //error
         try {
-            Function<var, String> f = (var x2) -> ""; //error
+            Function<var, String> f = (var x2) -> ""; //ok
         } catch (var ex) { } //error
     }
 
--- a/test/langtools/tools/javac/lvti/ParserTest.out	Tue Sep 26 15:24:57 2017 +0200
+++ b/test/langtools/tools/javac/lvti/ParserTest.out	Wed Sep 27 12:57:41 2017 +0100
@@ -18,8 +18,7 @@
 ParserTest.java:60:24: compiler.err.var.not.allowed.here
 ParserTest.java:61:22: compiler.err.var.not.allowed.here
 ParserTest.java:63:22: compiler.err.var.not.allowed.here
-ParserTest.java:63:40: compiler.err.var.not.allowed.here
 ParserTest.java:64:18: compiler.err.var.not.allowed.here
 ParserTest.java:68:35: compiler.err.var.not.allowed.here
 ParserTest.java:69:22: compiler.err.var.not.allowed.here
-24 errors
+23 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/VarNotAllowedExplicitLambda.java	Wed Sep 27 12:57:41 2017 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, 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.var.not.allowed.explicit.lambda
+
+class VarNotAllowedExplicitLambda {
+    F f = (String s, var v)->{};
+}