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