提交 d561b0cc 编写于 作者: M mcimadamore

8005854: Add support for array constructor references

Summary: Support constructor references of the kind int[]::new
Reviewed-by: jjg
上级 6ad85204
......@@ -634,25 +634,40 @@ public class Check {
}
}
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 @@ public class Check {
* @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 {
......
......@@ -302,6 +302,7 @@ public class LambdaToMethod extends TreeTranslator {
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 @@ public class LambdaToMethod extends TreeTranslator {
* 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) {
......
......@@ -2386,10 +2386,23 @@ public class Resolve {
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);
......@@ -2626,6 +2639,33 @@ public class Resolve {
}
}
/**
* 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
......
......@@ -1838,7 +1838,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/** 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;
......
/*
* 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);
}
}
/*
* 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
}
}
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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册