8005854: Add support for array constructor references
Summary: Support constructor references of the kind int[]::new
Reviewed-by: jjg
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Jan 15 13:03:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jan 16 16:27:01 2013 +0000
@@ -634,25 +634,40 @@
}
}
+ Type checkClassOrArrayType(DiagnosticPosition pos, Type t) {
+ if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) {
+ return typeTagError(pos,
+ diags.fragment("type.req.class.array"),
+ asTypeParam(t));
+ } else {
+ return t;
+ }
+ }
+
/** Check that type is a class or interface type.
* @param pos Position to be used for error reporting.
* @param t The type to be checked.
*/
Type checkClassType(DiagnosticPosition pos, Type t) {
- if (!t.hasTag(CLASS) && !t.hasTag(ERROR))
+ if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) {
return typeTagError(pos,
diags.fragment("type.req.class"),
- (t.hasTag(TYPEVAR))
- ? diags.fragment("type.parameter", t)
- : t);
- else
+ asTypeParam(t));
+ } else {
return t;
+ }
}
+ //where
+ private Object asTypeParam(Type t) {
+ return (t.hasTag(TYPEVAR))
+ ? diags.fragment("type.parameter", t)
+ : t;
+ }
/** Check that type is a valid qualifier for a constructor reference expression
*/
Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
- t = checkClassType(pos, t);
+ t = checkClassOrArrayType(pos, t);
if (t.hasTag(CLASS)) {
if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
log.error(pos, "abstract.cant.be.instantiated");
@@ -690,11 +705,8 @@
* @param t The type to be checked.
*/
Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) {
- if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) {
- return typeTagError(pos,
- diags.fragment("type.req.class.array"),
- t);
- } else if (!types.isReifiable(t)) {
+ t = checkClassOrArrayType(pos, t);
+ if (!t.isErroneous() && !types.isReifiable(t)) {
log.error(pos, "illegal.generic.type.for.instof");
return types.createErrorType(t);
} else {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Tue Jan 15 13:03:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Jan 16 16:27:01 2013 +0000
@@ -302,6 +302,7 @@
case UNBOUND: /** Type :: instMethod */
case STATIC: /** Type :: staticMethod */
case TOPLEVEL: /** Top level :: new */
+ case ARRAY_CTOR: /** ArrayType :: new */
init = null;
break;
@@ -645,24 +646,33 @@
* to the first bridge synthetic parameter
*/
private JCExpression bridgeExpressionNew() {
- JCExpression encl = null;
- switch (tree.kind) {
- case UNBOUND:
- case IMPLICIT_INNER:
- encl = make.Ident(params.first());
- }
+ if (tree.kind == ReferenceKind.ARRAY_CTOR) {
+ //create the array creation expression
+ JCNewArray newArr = make.NewArray(make.Type(types.elemtype(tree.getQualifierExpression().type)),
+ List.of(make.Ident(params.first())),
+ null);
+ newArr.type = tree.getQualifierExpression().type;
+ return newArr;
+ } else {
+ JCExpression encl = null;
+ switch (tree.kind) {
+ case UNBOUND:
+ case IMPLICIT_INNER:
+ encl = make.Ident(params.first());
+ }
- //create the instance creation expression
- JCNewClass newClass = make.NewClass(encl,
- List.<JCExpression>nil(),
- make.Type(tree.getQualifierExpression().type),
- convertArgs(tree.sym, args.toList(), tree.varargsElement),
- null);
- newClass.constructor = tree.sym;
- newClass.constructorType = tree.sym.erasure(types);
- newClass.type = tree.getQualifierExpression().type;
- setVarargsIfNeeded(newClass, tree.varargsElement);
- return newClass;
+ //create the instance creation expression
+ JCNewClass newClass = make.NewClass(encl,
+ List.<JCExpression>nil(),
+ make.Type(tree.getQualifierExpression().type),
+ convertArgs(tree.sym, args.toList(), tree.varargsElement),
+ null);
+ newClass.constructor = tree.sym;
+ newClass.constructorType = tree.sym.erasure(types);
+ newClass.type = tree.getQualifierExpression().type;
+ setVarargsIfNeeded(newClass, tree.varargsElement);
+ return newClass;
+ }
}
private VarSymbol addParameter(String name, Type p, boolean genArg) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Tue Jan 15 13:03:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jan 16 16:27:01 2013 +0000
@@ -2386,10 +2386,23 @@
List<Type> typeargtypes,
boolean boxingAllowed) {
MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
+
+ ReferenceLookupHelper boundLookupHelper;
+ if (!name.equals(names.init)) {
+ //method reference
+ boundLookupHelper =
+ new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
+ } else if (site.hasTag(ARRAY)) {
+ //array constructor reference
+ boundLookupHelper =
+ new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
+ } else {
+ //class constructor reference
+ boundLookupHelper =
+ new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
+ }
+
//step 1 - bound lookup
- ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ?
- new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase) :
- new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper);
@@ -2627,6 +2640,33 @@
}
/**
+ * Helper class for array constructor lookup; an array constructor lookup
+ * is simulated by looking up a method that returns the array type specified
+ * as qualifier, and that accepts a single int parameter (size of the array).
+ */
+ class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper {
+
+ ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes,
+ List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
+ super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase);
+ }
+
+ @Override
+ protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+ Scope sc = new Scope(syms.arrayClass);
+ MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym);
+ arrayConstr.type = new MethodType(List.of(syms.intType), site, List.<Type>nil(), syms.methodClass);
+ sc.enter(arrayConstr);
+ return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false, false);
+ }
+
+ @Override
+ ReferenceKind referenceKind(Symbol sym) {
+ return ReferenceKind.ARRAY_CTOR;
+ }
+ }
+
+ /**
* Helper class for constructor reference lookup. The lookup logic is based
* upon either Resolve.findMethod or Resolve.findDiamond - depending on
* whether the constructor reference needs diamond inference (this is the case
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Tue Jan 15 13:03:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Jan 16 16:27:01 2013 +0000
@@ -1838,7 +1838,9 @@
/** Inner # new */
IMPLICIT_INNER(ReferenceMode.NEW, false),
/** Toplevel # new */
- TOPLEVEL(ReferenceMode.NEW, false);
+ TOPLEVEL(ReferenceMode.NEW, false),
+ /** ArrayType # new */
+ ARRAY_CTOR(ReferenceMode.NEW, false);
final ReferenceMode mode;
final boolean unbound;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference59.java Wed Jan 16 16:27:01 2013 +0000
@@ -0,0 +1,52 @@
+/*
+ * 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 8004102
+ * @summary Add support for array constructor references
+ */
+public class MethodReference59 {
+
+ static int assertionCount = 0;
+
+ static void assertTrue(boolean cond) {
+ assertionCount++;
+ if (!cond)
+ throw new AssertionError();
+ }
+
+ interface ArrayFactory<X> {
+ X make(int size);
+ }
+
+ public static void main(String[] args) {
+ ArrayFactory<int[]> factory1 = int[]::new;
+ int[] i1 = factory1.make(5);
+ assertTrue(i1.length == 5);
+ ArrayFactory<int[][]> factory2 = int[][]::new;
+ int[][] i2 = factory2.make(5);
+ assertTrue(i2.length == 5);
+ assertTrue(assertionCount == 2);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference60.java Wed Jan 16 16:27:01 2013 +0000
@@ -0,0 +1,55 @@
+/*
+ * 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 8004102
+ * @summary Add support for array constructor references
+ * @compile/fail/ref=MethodReference60.out -XDrawDiagnostics MethodReference60.java
+ */
+public class MethodReference60 {
+
+ interface ArrayFactory<X> {
+ X make(int size);
+ }
+
+ interface BadArrayFactory1<X> {
+ X make();
+ }
+
+ interface BadArrayFactory2<X> {
+ X make(int i1, int i2);
+ }
+
+ interface BadArrayFactory3<X> {
+ X make(String s);
+ }
+
+ public static void main(String[] args) {
+ BadArrayFactory1<int[]> factory1 = int[]::new; //param mismatch
+ BadArrayFactory2<int[]> factory2 = int[]::new; //param mismatch
+ BadArrayFactory3<int[]> factory3 = int[]::new; //param mismatch
+ ArrayFactory<Integer> factory4 = int[]::new; //return type mismatch
+ ArrayFactory<Integer[]> factory5 = int[]::new; //return type mismatch
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference60.out Wed Jan 16 16:27:01 2013 +0000
@@ -0,0 +1,6 @@
+MethodReference60.java:49:44: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Array, int, compiler.misc.no.args, kindname.class, Array, (compiler.misc.arg.length.mismatch)))
+MethodReference60.java:50:44: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Array, int, int,int, kindname.class, Array, (compiler.misc.arg.length.mismatch)))
+MethodReference60.java:51:44: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Array, int, java.lang.String, kindname.class, Array, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, int))))
+MethodReference60.java:52:42: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: int[], java.lang.Integer))
+MethodReference60.java:53:44: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: int[], java.lang.Integer[]))
+5 errors