8004101: Add checks for method reference well-formedness
Summary: Bring method reference type-checking in sync with latest EDR
Reviewed-by: jjg
--- 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)");