Added basic support for constructor references.
authormcimadamore
Mon Jan 17 14:34:40 2011 +0000 (16 months ago)
changeset 8559a616df38d88
parent 85489631f9e86b7
child 856a953c0c02c7c
Added basic support for constructor references.
Syntax is as follows:

ClassName [optionalTypeArgs] '#' 'new' [optionalArgs]

Examples:

Foo#new -> (*)Foo [most specific constructor]
Foo#new() -> ()Foo
Foo#new("Hello!") -> (String)Foo
Foo<String>#new("Hello!") -> (String)Foo<String>
src/share/classes/com/sun/tools/javac/comp/Attr.java
src/share/classes/com/sun/tools/javac/comp/Lower.java
src/share/classes/com/sun/tools/javac/parser/JavacParser.java
test/tools/javac/lambda/MethodReference17.java
test/tools/javac/lambda/MethodReference18.java
test/tools/javac/lambda/MethodReference19.java
test/tools/javac/lambda/MethodReference20.java
test/tools/javac/lambda/MethodReference20.out
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jan 06 13:19:18 2011 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Jan 17 14:34:40 2011 +0000
@@ -2751,6 +2751,7 @@ public class Attr extends JCTree.Visitor
Symbol sym = null;
Type owntype = null;
switch (tree.mode) {
+ case NEW:
case INVOKE:
JCMethodInvocation apply = (JCMethodInvocation) expr;
Type mtype = attribExpr(apply, localEnv);
@@ -2799,11 +2800,14 @@ public class Attr extends JCTree.Visitor
Type mtype = tree.meth.type;
List<Type> args = mtype.getParameterTypes();
if (!msym.isStatic() &&
+ !msym.isConstructor() &&
TreeInfo.isStaticSelector(base, names)) {
args = args.prepend(base.type);
}
return new FunctionType(args,
- mtype.getReturnType(),
+ msym.isConstructor() ?
+ base.type :
+ mtype.getReturnType(),
mtype.getThrownTypes(),
syms.methodHandleType.tsym);
}
--- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Jan 06 13:19:18 2011 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Mon Jan 17 14:34:40 2011 +0000
@@ -2896,7 +2896,8 @@ public class Lower extends TreeTranslato
@Override
public void visitReference(JCMemberReference tree) {
if (tree.expr.getTag() != JCTree.APPLY ||
- tree.getMode() != ReferenceMode.INVOKE) {
+ !(tree.getMode() == ReferenceMode.INVOKE ||
+ tree.getMode() == ReferenceMode.NEW)) {
throw new AssertionError();
}
JCMethodInvocation apply = (JCMethodInvocation)tree.expr;
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Jan 06 13:19:18 2011 +0000
+++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Jan 17 14:34:40 2011 +0000
@@ -1593,7 +1593,9 @@ public class JavacParser implements Pars
/**
* MemberReferenceSuffix = "#" Ident
+ * | "#" "new"
* | "#" [TypeArguments] Ident MethodParameterTypes
+ * | "#" [TypeArguments] "new" MethodParameterTypes
*/
JCExpression memberReferenceSuffix(JCExpression t) {
int pos1 = S.pos();
@@ -1608,7 +1610,17 @@ public class JavacParser implements Pars
if (S.token() == LT) {
typeArgs = typeArguments();
}
- t = toP(F.at(pos1).Select(t, ident()));
+ Name refName = null;
+ ReferenceMode refMode = null;
+ if (S.token() == NEW) {
+ refMode = ReferenceMode.NEW;
+ refName = names.init;
+ S.nextToken();
+ } else {
+ refMode = ReferenceMode.INVOKE;
+ refName = ident();
+ }
+ t = toP(F.at(pos1).Select(t, refName));
int pos2 = S.pos();
if (S.token() == LPAREN) {
List<JCExpression> types = methodParameterTypes();
@@ -1617,7 +1629,7 @@ public class JavacParser implements Pars
else {
t = toP(F.at(pos2).Apply(typeArgs, t, null, true));
}
- return toP(F.at(t.getStartPosition()).Reference(ReferenceMode.INVOKE, t));
+ return toP(F.at(t.getStartPosition()).Reference(refMode, t));
}
/** MethodParameterTypes = "(" [ typeList ] ")"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference17.java Mon Jan 17 14:34:40 2011 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011, 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
+ * @summary basic test for constructor references
+ * @author Maurizio Cimadamore
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles MethodReference17
+ */
+
+public class MethodReference17 {
+
+ static void assertTrue(boolean cond) {
+ assertionCount++;
+ if (!cond)
+ throw new AssertionError();
+ }
+
+ static int assertionCount = 0;
+
+ MethodReference17() {
+ assertTrue(true);
+ }
+
+ interface SAM1 {
+ MethodReference17 m();
+ }
+
+ static abstract class SAM2 {
+ abstract MethodReference17 m();
+ }
+
+ static void test1(SAM1 s1) {
+ s1.m();
+ }
+
+ static void test2(SAM2 s2) {
+ s2.m();
+ }
+
+ public static void main(String[] args) {
+ SAM1 s1 = MethodReference17#new;
+ s1.m();
+ SAM2 s2 = MethodReference17#new;
+ s2.m();
+ test1(MethodReference17#new);
+ test2(MethodReference17#new);
+ assertTrue(assertionCount == 4);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference18.java Mon Jan 17 14:34:40 2011 +0000
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011, 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
+ * @summary basic test for constructor references
+ * @author Maurizio Cimadamore
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles MethodReference18
+ */
+
+public class MethodReference18 {
+
+ static void assertTrue(boolean cond) {
+ assertionCount++;
+ if (!cond)
+ throw new AssertionError();
+ }
+
+ static int assertionCount = 0;
+
+ MethodReference18(Object o) {
+ assertTrue(true);
+ }
+
+ MethodReference18(Number n) {
+ assertTrue(false);
+ }
+
+ interface SAM1 {
+ MethodReference18 m(Object o);
+ }
+
+ static abstract class SAM2 {
+ abstract MethodReference18 m(Object o);
+ }
+
+ static void test1(SAM1 s1, Object arg) {
+ s1.m(arg);
+ }
+
+ static void test2(SAM2 s2, Object arg) {
+ s2.m(arg);
+ }
+
+ public static void main(String[] args) {
+ SAM1 s1 = MethodReference18#new(Object);
+ s1.m("");
+ SAM2 s2 = MethodReference18#new(Object);
+ s2.m("");
+ test1(MethodReference18#new(Object), "");
+ test2(MethodReference18#new(Object), "");
+ assertTrue(assertionCount == 4);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference19.java Mon Jan 17 14:34:40 2011 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011, 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
+ * @summary basic test for constructor references and generic classes
+ * @author Maurizio Cimadamore
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles MethodReference19
+ */
+
+public class MethodReference19<X> {
+
+ static void assertTrue(boolean cond) {
+ assertionCount++;
+ if (!cond)
+ throw new AssertionError();
+ }
+
+ static int assertionCount = 0;
+
+ MethodReference19(X x) {
+ assertTrue(true);
+ }
+
+ interface SAM1<Z> {
+ MethodReference19<Z> m(Z z);
+ }
+
+ static abstract class SAM2<Z> {
+ abstract MethodReference19<Z> m(Z z);
+ }
+
+ static <Y> void test1(SAM1<Y> s1, Y arg) {
+ s1.m(arg);
+ }
+
+ static <Y> void test2(SAM2<Y> s2, Y arg) {
+ s2.m(arg);
+ }
+
+ public static void main(String[] args) {
+ SAM1<String> s1 = MethodReference19<String>#new;
+ s1.m("");
+ SAM2<String> s2 = MethodReference19<String>#new;
+ s2.m("");
+ test1(MethodReference19<String>#new, "");
+ test2(MethodReference19<String>#new, "");
+ assertTrue(assertionCount == 4);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference20.java Mon Jan 17 14:34:40 2011 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011, 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
+ * @summary basic test for constructor references and generic classes
+ * @author Maurizio Cimadamore
+ * @compile/fail/ref=MethodReference20.out -XDrawDiagnostics MethodReference20.java
+ */
+
+class MethodReference20<X> {
+
+ MethodReference20(X x) { }
+
+ interface SAM<Z> {
+ MethodReference20<Z> m(Z z);
+ }
+
+ static void test(SAM<Integer> s) { }
+
+ public static void main(String[] args) {
+ SAM<Integer> s1 = MethodReference20<String>#new;
+ SAM<Integer> s2 = MethodReference20<String>#new(Integer);
+ test(MethodReference20<String>#new);
+ test(MethodReference20<String>#new(Integer));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference20.out Mon Jan 17 14:34:40 2011 +0000
@@ -0,0 +1,5 @@
+MethodReference20.java:42:27: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.incompatible.target.in.lambda.conv: m, kindname.interface, MethodReference20.SAM)), #MethodReference20<java.lang.String>(java.lang.String), MethodReference20.SAM<java.lang.Integer>
+MethodReference20.java:43:53: compiler.err.cant.apply.symbol.1: kindname.constructor, MethodReference20, java.lang.String, java.lang.Integer, kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists: java.lang.Integer, java.lang.String, null)
+MethodReference20.java:44:9: compiler.err.cant.apply.symbol.1: kindname.method, test, MethodReference20.SAM<java.lang.Integer>, #MethodReference20<java.lang.String>(java.lang.String), kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists.1: #MethodReference20<java.lang.String>(java.lang.String), MethodReference20.SAM<java.lang.Integer>, (compiler.misc.incompatible.target.in.lambda.conv: m, kindname.interface, MethodReference20.SAM))
+MethodReference20.java:45:40: compiler.err.cant.apply.symbol.1: kindname.constructor, MethodReference20, java.lang.String, java.lang.Integer, kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists: java.lang.Integer, java.lang.String, null)
+4 errors