mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-20 07:15:31 +00:00
8005854: Add support for array constructor references
Support constructor references of the kind int[]::new Reviewed-by: jjg
This commit is contained in:
parent
f8b61f9b0c
commit
d19bc80ca1
@ -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;
|
||||
|
||||
52
langtools/test/tools/javac/lambda/MethodReference59.java
Normal file
52
langtools/test/tools/javac/lambda/MethodReference59.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
55
langtools/test/tools/javac/lambda/MethodReference60.java
Normal file
55
langtools/test/tools/javac/lambda/MethodReference60.java
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
6
langtools/test/tools/javac/lambda/MethodReference60.out
Normal file
6
langtools/test/tools/javac/lambda/MethodReference60.out
Normal file
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user