8004101: Add checks for method reference well-formedness
authormcimadamore
Fri, 30 Nov 2012 15:14:36 +0000
changeset 14724 b542db73539a
parent 14723 46aa71a5e4e0
child 14725 65836e833f59
8004101: Add checks for method reference well-formedness Summary: Bring method reference type-checking in sync with latest EDR Reviewed-by: jjg
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java
langtools/test/tools/javac/diags/examples/StaticBoundMref.java
langtools/test/tools/javac/diags/examples/StaticMrefWithTargs.java
langtools/test/tools/javac/lambda/MethodReference30.java
langtools/test/tools/javac/lambda/MethodReference55.java
langtools/test/tools/javac/lambda/MethodReference55.out
langtools/test/tools/javac/lambda/MethodReference56.java
langtools/test/tools/javac/lambda/MethodReference56.out
langtools/test/tools/javac/lambda/methodReference/MethodRef1.java
langtools/test/tools/javac/lambda/methodReference/SamConversion.java
langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestKinds.java
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Nov 30 15:14:25 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Nov 30 15:14:36 2012 +0000
@@ -2458,7 +2458,7 @@
             }
 
             //attrib type-arguments
-            List<Type> typeargtypes = null;
+            List<Type> typeargtypes = List.nil();
             if (that.typeargs != null) {
                 typeargtypes = attribTypes(that.typeargs, localEnv);
             }
@@ -2528,6 +2528,26 @@
                 }
             }
 
+            if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
+                if (refSym.isStatic() && TreeInfo.isStaticSelector(that.expr, names) &&
+                        exprType.getTypeArguments().nonEmpty()) {
+                    //static ref with class type-args
+                    log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()),
+                            diags.fragment("static.mref.with.targs"));
+                    result = that.type = types.createErrorType(target);
+                    return;
+                }
+
+                if (refSym.isStatic() && !TreeInfo.isStaticSelector(that.expr, names) &&
+                        !lookupHelper.referenceKind(refSym).isUnbound()) {
+                    //no static bound mrefs
+                    log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()),
+                            diags.fragment("static.bound.mref"));
+                    result = that.type = types.createErrorType(target);
+                    return;
+                }
+            }
+
             if (desc.getReturnType() == Type.recoveryType) {
                 // stop here
                 result = that.type = target;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Nov 30 15:14:25 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Nov 30 15:14:36 2012 +0000
@@ -288,21 +288,20 @@
         JCExpression init;
         switch(tree.kind) {
 
-            case IMPLICIT_INNER:    /** Inner # new */
-            case SUPER:             /** super # instMethod */
+            case IMPLICIT_INNER:    /** Inner :: new */
+            case SUPER:             /** super :: instMethod */
                 init = makeThis(
                     localContext.owner.owner.asType(),
                     localContext.owner);
                 break;
 
-            case BOUND:             /** Expr # instMethod */
+            case BOUND:             /** Expr :: instMethod */
                 init = tree.getQualifierExpression();
                 break;
 
-            case STATIC_EVAL:       /** Expr # staticMethod */
-            case UNBOUND:           /** Type # instMethod */
-            case STATIC:            /** Type # staticMethod */
-            case TOPLEVEL:          /** Top level # new */
+            case UNBOUND:           /** Type :: instMethod */
+            case STATIC:            /** Type :: staticMethod */
+            case TOPLEVEL:          /** Top level :: new */
                 init = null;
                 break;
 
@@ -315,14 +314,6 @@
 
         //build a sam instance using an indy call to the meta-factory
         result = makeMetaFactoryIndyCall(tree, tree.targetType, localContext.referenceKind(), refSym, indy_args);
-
-        //if we had a static reference with non-static qualifier, add a let
-        //expression to force the evaluation of the qualifier expr
-        if (tree.hasKind(ReferenceKind.STATIC_EVAL)) {
-            VarSymbol rec = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner);
-            JCVariableDecl recDef = make.VarDef(rec, tree.getQualifierExpression());
-            result = make.LetExpr(recDef, result).setType(tree.type);
-        }
     }
 
     /**
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Nov 30 15:14:25 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Nov 30 15:14:36 2012 +0000
@@ -2617,8 +2617,7 @@
         @Override
         ReferenceKind referenceKind(Symbol sym) {
             if (sym.isStatic()) {
-                return TreeInfo.isStaticSelector(referenceTree.expr, names) ?
-                        ReferenceKind.STATIC : ReferenceKind.STATIC_EVAL;
+                return ReferenceKind.STATIC;
             } else {
                 Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
                 return selName != null && selName == names._super ?
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Nov 30 15:14:25 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Nov 30 15:14:36 2012 +0000
@@ -215,6 +215,12 @@
 compiler.misc.invalid.mref=\
     invalid {0} reference; {1}
 
+compiler.misc.static.mref.with.targs=\
+    parameterized qualifier on static method reference
+
+compiler.misc.static.bound.mref=\
+    static bound method reference
+
 # 0: symbol
 compiler.err.cant.assign.val.to.final.var=\
     cannot assign a value to final variable {0}
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Fri Nov 30 15:14:25 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Fri Nov 30 15:14:36 2012 +0000
@@ -1829,8 +1829,6 @@
             STATIC(ReferenceMode.INVOKE, false),
             /** Expr # instMethod */
             BOUND(ReferenceMode.INVOKE, false),
-            /** Expr # staticMethod */
-            STATIC_EVAL(ReferenceMode.INVOKE, false),
             /** Inner # new */
             IMPLICIT_INNER(ReferenceMode.NEW, false),
             /** Toplevel # new */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/StaticBoundMref.java	Fri Nov 30 15:14:36 2012 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 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.invalid.mref
+// key: compiler.misc.static.bound.mref
+
+class StaticBoundMref {
+
+    Runnable r = new StaticBoundMref()::m;
+
+    static void m() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/StaticMrefWithTargs.java	Fri Nov 30 15:14:36 2012 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 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.invalid.mref
+// key: compiler.misc.static.mref.with.targs
+
+class StaticMrefWithTargs<X> {
+
+    Runnable r = StaticMrefWithTargs<String>::m;
+
+    static void m() { }
+}
--- a/langtools/test/tools/javac/lambda/MethodReference30.java	Fri Nov 30 15:14:25 2012 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference30.java	Fri Nov 30 15:14:36 2012 +0000
@@ -46,7 +46,7 @@
         assertTrue(true);
     }
 
-   static void m() { }
+   void m() { }
 
    public static void main(String[] args) {
       SAM s = new MethodReference30()::m;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference55.java	Fri Nov 30 15:14:36 2012 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 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
+ * @bug 8004101
+ * @summary Add checks for method reference well-formedness
+ * @compile/fail/ref=MethodReference55.out -XDrawDiagnostics MethodReference55.java
+ */
+class MethodReference55<X> {
+
+    interface V {
+        void m(Object o);
+    }
+
+    V v = new MethodReference55<String>()::m;
+
+    void test() {
+        g(new MethodReference55<String>()::m);
+    }
+
+    void g(V v) { }
+
+    static void m(Object o) { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference55.out	Fri Nov 30 15:14:36 2012 +0000
@@ -0,0 +1,3 @@
+MethodReference55.java:36:11: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.bound.mref)
+MethodReference55.java:39:11: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.bound.mref)
+2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference56.java	Fri Nov 30 15:14:36 2012 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 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
+ * @bug 8004101
+ * @summary Add checks for method reference well-formedness
+ * @compile/fail/ref=MethodReference56.out -XDrawDiagnostics MethodReference56.java
+ */
+class MethodReference56<X> {
+
+    interface V {
+        void m(Object o);
+    }
+
+    V v = MethodReference56<String>::m;
+
+    void test() {
+        g(MethodReference56<String>::m);
+    }
+
+    void g(V v) { }
+
+    static void m(Object o) { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference56.out	Fri Nov 30 15:14:36 2012 +0000
@@ -0,0 +1,3 @@
+MethodReference56.java:36:28: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.mref.with.targs)
+MethodReference56.java:39:28: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.mref.with.targs)
+2 errors
--- a/langtools/test/tools/javac/lambda/methodReference/MethodRef1.java	Fri Nov 30 15:14:25 2012 +0000
+++ b/langtools/test/tools/javac/lambda/methodReference/MethodRef1.java	Fri Nov 30 15:14:36 2012 +0000
@@ -70,9 +70,6 @@
         b = MethodRef1::foo; //static reference to foo(int)
         b.m(1);
 
-        b = new MethodRef1()::foo; //instance reference to static methods, supported for now
-        b.m(1);
-
         b = MethodRef1::bar; //static reference to bar(int)
         b.m(2);
 
--- a/langtools/test/tools/javac/lambda/methodReference/SamConversion.java	Fri Nov 30 15:14:25 2012 +0000
+++ b/langtools/test/tools/javac/lambda/methodReference/SamConversion.java	Fri Nov 30 15:14:36 2012 +0000
@@ -133,15 +133,6 @@
         } catch (Exception e) {
             assertTrue(false);
         }
-
-        bar = new A()::method6;
-        try {
-            bar.m(1);
-            assertTrue(false);
-        } catch (MyException e) {
-        } catch (Exception e) {
-            assertTrue(false);
-        }
     }
 
     /**
--- a/langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestKinds.java	Fri Nov 30 15:14:25 2012 +0000
+++ b/langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestKinds.java	Fri Nov 30 15:14:36 2012 +0000
@@ -119,20 +119,6 @@
         assertEquals(var.get(inst("arg")), "SM:1-MethodReferenceTestKinds(arg)");
     }
 
-    public void testMRStaticEval() {
-        MethodReferenceTestKinds evalCheck;
-        S0 var = (evalCheck = inst("discard"))::staticMethod0;
-        assertEquals(evalCheck.toString(), "MethodReferenceTestKinds(discard)");
-        assertEquals(var.get(), "SM:0");
-    }
-
-    public void testMRStaticEvalArg() {
-        MethodReferenceTestKinds evalCheck;
-        S1 var = (evalCheck = inst("discard"))::staticMethod1;
-        assertEquals(evalCheck.toString(), "MethodReferenceTestKinds(discard)");
-        assertEquals(var.get(inst("arg")), "SM:1-MethodReferenceTestKinds(arg)");
-    }
-
     public void testMRTopLevel() {
         SN0 var = MethodReferenceTestKindsBase::new;
         assertEquals(var.make().toString(), "MethodReferenceTestKindsBase(blank)");
@@ -142,17 +128,7 @@
         SN1 var = MethodReferenceTestKindsBase::new;
         assertEquals(var.make("name").toString(), "MethodReferenceTestKindsBase(name)");
     }
-/* unbound inner case not supported anymore (dropped by EG)
-    public void testMRUnboundInner() {
-        SXN0 var = MethodReferenceTestKinds.In::new;
-        assertEquals(var.make(inst("out")).toString(), "In(blank)");
-    }
 
-   public void testMRUnboundInnerArg() {
-        SXN1 var = MethodReferenceTestKinds.In::new;
-        assertEquals(var.make(inst("out"), "name").toString(), "In(name)");
-    }
-*/
     public void testMRImplicitInner() {
         SN0 var = MethodReferenceTestKinds.In::new;
         assertEquals(var.make().toString(), "In(blank)");