changeset 855:9a616df38d88

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>
author mcimadamore
date Mon, 17 Jan 2011 14:34:40 +0000
parents 89631f9e86b7
children a953c0c02c7c
files 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
diffstat 8 files changed, 287 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
         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 @@
         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 @@
     @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 @@
 
     /**
      * MemberReferenceSuffix = "#" Ident
+     *                       | "#" "new"
      *                       | "#" [TypeArguments] Ident MethodParameterTypes
+     *                       | "#" [TypeArguments] "new" MethodParameterTypes
      */
     JCExpression memberReferenceSuffix(JCExpression t) {
         int pos1 = S.pos();
@@ -1608,7 +1610,17 @@
         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 @@
         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