Wed, 16 Jan 2013 16:27:01 +0000
8005854: Add support for array constructor references
Summary: Support constructor references of the kind int[]::new
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Jan 15 13:03:11 2013 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jan 16 16:27:01 2013 +0000 1.3 @@ -634,25 +634,40 @@ 1.4 } 1.5 } 1.6 1.7 + Type checkClassOrArrayType(DiagnosticPosition pos, Type t) { 1.8 + if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { 1.9 + return typeTagError(pos, 1.10 + diags.fragment("type.req.class.array"), 1.11 + asTypeParam(t)); 1.12 + } else { 1.13 + return t; 1.14 + } 1.15 + } 1.16 + 1.17 /** Check that type is a class or interface type. 1.18 * @param pos Position to be used for error reporting. 1.19 * @param t The type to be checked. 1.20 */ 1.21 Type checkClassType(DiagnosticPosition pos, Type t) { 1.22 - if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) 1.23 + if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) { 1.24 return typeTagError(pos, 1.25 diags.fragment("type.req.class"), 1.26 - (t.hasTag(TYPEVAR)) 1.27 - ? diags.fragment("type.parameter", t) 1.28 - : t); 1.29 - else 1.30 + asTypeParam(t)); 1.31 + } else { 1.32 return t; 1.33 + } 1.34 } 1.35 + //where 1.36 + private Object asTypeParam(Type t) { 1.37 + return (t.hasTag(TYPEVAR)) 1.38 + ? diags.fragment("type.parameter", t) 1.39 + : t; 1.40 + } 1.41 1.42 /** Check that type is a valid qualifier for a constructor reference expression 1.43 */ 1.44 Type checkConstructorRefType(DiagnosticPosition pos, Type t) { 1.45 - t = checkClassType(pos, t); 1.46 + t = checkClassOrArrayType(pos, t); 1.47 if (t.hasTag(CLASS)) { 1.48 if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { 1.49 log.error(pos, "abstract.cant.be.instantiated"); 1.50 @@ -690,11 +705,8 @@ 1.51 * @param t The type to be checked. 1.52 */ 1.53 Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { 1.54 - if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { 1.55 - return typeTagError(pos, 1.56 - diags.fragment("type.req.class.array"), 1.57 - t); 1.58 - } else if (!types.isReifiable(t)) { 1.59 + t = checkClassOrArrayType(pos, t); 1.60 + if (!t.isErroneous() && !types.isReifiable(t)) { 1.61 log.error(pos, "illegal.generic.type.for.instof"); 1.62 return types.createErrorType(t); 1.63 } else {
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Tue Jan 15 13:03:11 2013 -0800 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Jan 16 16:27:01 2013 +0000 2.3 @@ -302,6 +302,7 @@ 2.4 case UNBOUND: /** Type :: instMethod */ 2.5 case STATIC: /** Type :: staticMethod */ 2.6 case TOPLEVEL: /** Top level :: new */ 2.7 + case ARRAY_CTOR: /** ArrayType :: new */ 2.8 init = null; 2.9 break; 2.10 2.11 @@ -645,24 +646,33 @@ 2.12 * to the first bridge synthetic parameter 2.13 */ 2.14 private JCExpression bridgeExpressionNew() { 2.15 - JCExpression encl = null; 2.16 - switch (tree.kind) { 2.17 - case UNBOUND: 2.18 - case IMPLICIT_INNER: 2.19 - encl = make.Ident(params.first()); 2.20 + if (tree.kind == ReferenceKind.ARRAY_CTOR) { 2.21 + //create the array creation expression 2.22 + JCNewArray newArr = make.NewArray(make.Type(types.elemtype(tree.getQualifierExpression().type)), 2.23 + List.of(make.Ident(params.first())), 2.24 + null); 2.25 + newArr.type = tree.getQualifierExpression().type; 2.26 + return newArr; 2.27 + } else { 2.28 + JCExpression encl = null; 2.29 + switch (tree.kind) { 2.30 + case UNBOUND: 2.31 + case IMPLICIT_INNER: 2.32 + encl = make.Ident(params.first()); 2.33 + } 2.34 + 2.35 + //create the instance creation expression 2.36 + JCNewClass newClass = make.NewClass(encl, 2.37 + List.<JCExpression>nil(), 2.38 + make.Type(tree.getQualifierExpression().type), 2.39 + convertArgs(tree.sym, args.toList(), tree.varargsElement), 2.40 + null); 2.41 + newClass.constructor = tree.sym; 2.42 + newClass.constructorType = tree.sym.erasure(types); 2.43 + newClass.type = tree.getQualifierExpression().type; 2.44 + setVarargsIfNeeded(newClass, tree.varargsElement); 2.45 + return newClass; 2.46 } 2.47 - 2.48 - //create the instance creation expression 2.49 - JCNewClass newClass = make.NewClass(encl, 2.50 - List.<JCExpression>nil(), 2.51 - make.Type(tree.getQualifierExpression().type), 2.52 - convertArgs(tree.sym, args.toList(), tree.varargsElement), 2.53 - null); 2.54 - newClass.constructor = tree.sym; 2.55 - newClass.constructorType = tree.sym.erasure(types); 2.56 - newClass.type = tree.getQualifierExpression().type; 2.57 - setVarargsIfNeeded(newClass, tree.varargsElement); 2.58 - return newClass; 2.59 } 2.60 2.61 private VarSymbol addParameter(String name, Type p, boolean genArg) {
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Tue Jan 15 13:03:11 2013 -0800 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jan 16 16:27:01 2013 +0000 3.3 @@ -2386,10 +2386,23 @@ 3.4 List<Type> typeargtypes, 3.5 boolean boxingAllowed) { 3.6 MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; 3.7 + 3.8 + ReferenceLookupHelper boundLookupHelper; 3.9 + if (!name.equals(names.init)) { 3.10 + //method reference 3.11 + boundLookupHelper = 3.12 + new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); 3.13 + } else if (site.hasTag(ARRAY)) { 3.14 + //array constructor reference 3.15 + boundLookupHelper = 3.16 + new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 3.17 + } else { 3.18 + //class constructor reference 3.19 + boundLookupHelper = 3.20 + new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 3.21 + } 3.22 + 3.23 //step 1 - bound lookup 3.24 - ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ? 3.25 - new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase) : 3.26 - new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); 3.27 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); 3.28 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper); 3.29 3.30 @@ -2627,6 +2640,33 @@ 3.31 } 3.32 3.33 /** 3.34 + * Helper class for array constructor lookup; an array constructor lookup 3.35 + * is simulated by looking up a method that returns the array type specified 3.36 + * as qualifier, and that accepts a single int parameter (size of the array). 3.37 + */ 3.38 + class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper { 3.39 + 3.40 + ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes, 3.41 + List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 3.42 + super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); 3.43 + } 3.44 + 3.45 + @Override 3.46 + protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 3.47 + Scope sc = new Scope(syms.arrayClass); 3.48 + MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym); 3.49 + arrayConstr.type = new MethodType(List.of(syms.intType), site, List.<Type>nil(), syms.methodClass); 3.50 + sc.enter(arrayConstr); 3.51 + return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false, false); 3.52 + } 3.53 + 3.54 + @Override 3.55 + ReferenceKind referenceKind(Symbol sym) { 3.56 + return ReferenceKind.ARRAY_CTOR; 3.57 + } 3.58 + } 3.59 + 3.60 + /** 3.61 * Helper class for constructor reference lookup. The lookup logic is based 3.62 * upon either Resolve.findMethod or Resolve.findDiamond - depending on 3.63 * whether the constructor reference needs diamond inference (this is the case
4.1 --- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java Tue Jan 15 13:03:11 2013 -0800 4.2 +++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Jan 16 16:27:01 2013 +0000 4.3 @@ -1838,7 +1838,9 @@ 4.4 /** Inner # new */ 4.5 IMPLICIT_INNER(ReferenceMode.NEW, false), 4.6 /** Toplevel # new */ 4.7 - TOPLEVEL(ReferenceMode.NEW, false); 4.8 + TOPLEVEL(ReferenceMode.NEW, false), 4.9 + /** ArrayType # new */ 4.10 + ARRAY_CTOR(ReferenceMode.NEW, false); 4.11 4.12 final ReferenceMode mode; 4.13 final boolean unbound;
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/lambda/MethodReference59.java Wed Jan 16 16:27:01 2013 +0000 5.3 @@ -0,0 +1,52 @@ 5.4 +/* 5.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +/* 5.28 + * @test 5.29 + * @bug 8004102 5.30 + * @summary Add support for array constructor references 5.31 + */ 5.32 +public class MethodReference59 { 5.33 + 5.34 + static int assertionCount = 0; 5.35 + 5.36 + static void assertTrue(boolean cond) { 5.37 + assertionCount++; 5.38 + if (!cond) 5.39 + throw new AssertionError(); 5.40 + } 5.41 + 5.42 + interface ArrayFactory<X> { 5.43 + X make(int size); 5.44 + } 5.45 + 5.46 + public static void main(String[] args) { 5.47 + ArrayFactory<int[]> factory1 = int[]::new; 5.48 + int[] i1 = factory1.make(5); 5.49 + assertTrue(i1.length == 5); 5.50 + ArrayFactory<int[][]> factory2 = int[][]::new; 5.51 + int[][] i2 = factory2.make(5); 5.52 + assertTrue(i2.length == 5); 5.53 + assertTrue(assertionCount == 2); 5.54 + } 5.55 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/lambda/MethodReference60.java Wed Jan 16 16:27:01 2013 +0000 6.3 @@ -0,0 +1,55 @@ 6.4 +/* 6.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +/* 6.28 + * @test 6.29 + * @bug 8004102 6.30 + * @summary Add support for array constructor references 6.31 + * @compile/fail/ref=MethodReference60.out -XDrawDiagnostics MethodReference60.java 6.32 + */ 6.33 +public class MethodReference60 { 6.34 + 6.35 + interface ArrayFactory<X> { 6.36 + X make(int size); 6.37 + } 6.38 + 6.39 + interface BadArrayFactory1<X> { 6.40 + X make(); 6.41 + } 6.42 + 6.43 + interface BadArrayFactory2<X> { 6.44 + X make(int i1, int i2); 6.45 + } 6.46 + 6.47 + interface BadArrayFactory3<X> { 6.48 + X make(String s); 6.49 + } 6.50 + 6.51 + public static void main(String[] args) { 6.52 + BadArrayFactory1<int[]> factory1 = int[]::new; //param mismatch 6.53 + BadArrayFactory2<int[]> factory2 = int[]::new; //param mismatch 6.54 + BadArrayFactory3<int[]> factory3 = int[]::new; //param mismatch 6.55 + ArrayFactory<Integer> factory4 = int[]::new; //return type mismatch 6.56 + ArrayFactory<Integer[]> factory5 = int[]::new; //return type mismatch 6.57 + } 6.58 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/tools/javac/lambda/MethodReference60.out Wed Jan 16 16:27:01 2013 +0000 7.3 @@ -0,0 +1,6 @@ 7.4 +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))) 7.5 +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))) 7.6 +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)))) 7.7 +MethodReference60.java:52:42: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: int[], java.lang.Integer)) 7.8 +MethodReference60.java:53:44: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: int[], java.lang.Integer[])) 7.9 +5 errors