6880344: Recursive type parameters do not compile

Wed, 19 May 2010 16:41:57 +0100

author
mcimadamore
date
Wed, 19 May 2010 16:41:57 +0100
changeset 561
e9ef849ae0ed
parent 560
ebf09be0222c
child 562
2881b376a689

6880344: Recursive type parameters do not compile
Summary: Issue in type-variable substitution causes valid code to be rejected
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/code/Types.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Check.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/typevars/T6880344.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java	Thu May 13 11:30:28 2010 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Wed May 19 16:41:57 2010 +0100
     1.3 @@ -588,10 +588,21 @@
     1.4                  case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
     1.5                  case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE:
     1.6                      return t.tag == s.tag;
     1.7 -                case TYPEVAR:
     1.8 -                    return s.isSuperBound()
     1.9 -                        && !s.isExtendsBound()
    1.10 -                        && visit(t, upperBound(s));
    1.11 +                case TYPEVAR: {
    1.12 +                    if (s.tag == TYPEVAR) {
    1.13 +                        //type-substitution does not preserve type-var types
    1.14 +                        //check that type var symbols and bounds are indeed the same
    1.15 +                        return t.tsym == s.tsym &&
    1.16 +                                visit(t.getUpperBound(), s.getUpperBound());
    1.17 +                    }
    1.18 +                    else {
    1.19 +                        //special case for s == ? super X, where upper(s) = u
    1.20 +                        //check that u == t, where u has been set by Type.withTypeVar
    1.21 +                        return s.isSuperBound() &&
    1.22 +                                !s.isExtendsBound() &&
    1.23 +                                visit(t, upperBound(s));
    1.24 +                    }
    1.25 +                }
    1.26                  default:
    1.27                      throw new AssertionError("isSameType " + t.tag);
    1.28                  }
     2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu May 13 11:30:28 2010 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Wed May 19 16:41:57 2010 +0100
     2.3 @@ -915,7 +915,7 @@
     2.4                  List<Type> actuals = tree.type.allparams();
     2.5                  List<JCExpression> args = tree.arguments;
     2.6                  List<Type> forms = tree.type.tsym.type.getTypeArguments();
     2.7 -                ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>();
     2.8 +                ListBuffer<Type> tvars_buf = new ListBuffer<Type>();
     2.9  
    2.10                  // For matching pairs of actual argument types `a' and
    2.11                  // formal type parameters with declared bound `b' ...
    2.12 @@ -946,12 +946,15 @@
    2.13                  }
    2.14  
    2.15                  args = tree.arguments;
    2.16 -                List<TypeVar> tvars = tvars_buf.toList();
    2.17 +                List<Type> tvars = tvars_buf.toList();
    2.18  
    2.19                  while (args.nonEmpty() && tvars.nonEmpty()) {
    2.20 +                    Type actual = types.subst(args.head.type,
    2.21 +                        tree.type.tsym.type.getTypeArguments(),
    2.22 +                        tvars_buf.toList());
    2.23                      checkExtends(args.head.pos(),
    2.24 -                                 args.head.type,
    2.25 -                                 tvars.head);
    2.26 +                                 actual,
    2.27 +                                 (TypeVar)tvars.head);
    2.28                      args = args.tail;
    2.29                      tvars = tvars.tail;
    2.30                  }
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/tools/javac/generics/typevars/T6880344.java	Wed May 19 16:41:57 2010 +0100
     3.3 @@ -0,0 +1,40 @@
     3.4 +/*
     3.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.
    3.11 + *
    3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.15 + * version 2 for more details (a copy is included in the LICENSE file that
    3.16 + * accompanied this code).
    3.17 + *
    3.18 + * You should have received a copy of the GNU General Public License version
    3.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.21 + *
    3.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    3.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    3.24 + * have any questions.
    3.25 + */
    3.26 +
    3.27 +/*
    3.28 + * @test
    3.29 + * @bug     6880344
    3.30 + * @summary Recursive type parameters do not compile
    3.31 + * @author  mcimadamore
    3.32 + * @compile T6880344.java
    3.33 + */
    3.34 +
    3.35 +class T6880344 {
    3.36 +    static class A<X1 extends G<X1>> {
    3.37 +        public A<N<X1>> xyz;
    3.38 +    }
    3.39 +
    3.40 +    static class N<X2 extends G<X2>> implements G<N<X2>> { }
    3.41 +
    3.42 +    interface G<X3 extends G<X3>> { }
    3.43 +}

mercurial