8005854: Add support for array constructor references

Wed, 16 Jan 2013 16:27:01 +0000

author
mcimadamore
date
Wed, 16 Jan 2013 16:27:01 +0000
changeset 1496
f785dcac17b7
parent 1495
bc1023e0e533
child 1497
7aa2025bbb7b

8005854: Add support for array constructor references
Summary: Support constructor references of the kind int[]::new
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/comp/Check.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Resolve.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/JCTree.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference59.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference60.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference60.out file | annotate | diff | comparison | revisions
     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

mercurial