test/tools/javac/generics/Nonlinear.java

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 1
9a66ca7c79fa
child 289
84061bd68019
permissions
-rw-r--r--

Initial load

     1 /*
     2  * Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  */
    24 /*
    25  * @test
    26  * @bug 4607420
    27  * @summary A bug in the original JSR14 generics specification
    28  *          created a loophole in the type system.
    29  *
    30  * @compile/fail -source 1.5 Nonlinear.java
    31  */
    34 public class Nonlinear {
    36     // This is an example of lack of type safety for
    37     // the version of javac from jsr14_adding_generics-1_0-ea
    39     // It is a variant of the "classic" problem with polymorphic
    40     // references in SML, which resulted in the usual array of
    41     // fixes: notably value polymorphism.
    43     // This code compiles, but produces a ClassCastException
    44     // when executed, even though there are no explicit casts in
    45     // the program.
    47     public static void main (String [] args) {
    48         Integer x = new Integer (5);
    49         String y = castit (x);
    50         System.out.println (y);
    51     }
    53     static <A,B> A castit (B x) {
    54         // This method casts any type to any other type.
    55         // Oh dear.  This shouldn't type check, but does
    56         // because build () returns a type Ref<*>
    57         // which is a subtype of RWRef<A,B>.
    58         final RWRef<A,B> r = build ();
    59         r.set (x);
    60         return r.get ();
    61     }
    63     static <A> Ref<A> build () {
    64         return new Ref<A> ();
    65     }
    67     // Another way of doing this is a variant of the crackit
    68     // example discussed in the draft specification.
    69     //
    70     // The original duplicate was:
    71     //
    72     // static <A> Pair <A,A> duplicate (A x) {
    73     //     return new Pair<A,A> (x,x);
    74     // }
    75     //
    76     // which breaks the requirement that a type variable
    77     // instantiated by * only occurs once in the result type.
    78     //
    79     // However, we can achieve the same result with a different
    80     // type for duplicate, which uses its type variables linearly
    81     // in the result:
    83     static <A,B extends Ref<A>> Pair<Ref<A>,B> duplicate (B x) {
    84         return new Pair<Ref<A>,B> (x,x);
    85     }
    87     // the cheat here is that A and B are used linearly in the result
    88     // type, but not in the polymorphic bounds.
    90     // We can use that to give an alternative implementation of
    91     // castit.
    93     static <A,B> A castit2 (B x) {
    94         Pair <Ref<A>, Ref<B>> p = duplicate (build ());
    95         p.snd.set (x);
    96         return p.fst.get ();
    97     }
   100 }
   102 interface RWRef<A,B> {
   104     public A get ();
   105     public void set (B x);
   107 }
   109 class Ref<A> implements RWRef <A,A> {
   111     A contents;
   113     public void set (A x) { contents = x; }
   114     public A get () { return contents; }
   116 }
   118 class Pair<A,B> {
   120     final A fst;
   121     final B snd;
   123     Pair (A fst, B snd) { this.fst = fst; this.snd = snd; }
   125 }

mercurial