0N/A/*
553N/A * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
553N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * @test
0N/A * @bug 4607420
0N/A * @summary A bug in the original JSR14 generics specification
0N/A * created a loophole in the type system.
0N/A *
288N/A * @compile/fail Nonlinear.java
0N/A */
0N/A
0N/A
0N/Apublic class Nonlinear {
0N/A
0N/A // This is an example of lack of type safety for
0N/A // the version of javac from jsr14_adding_generics-1_0-ea
0N/A
0N/A // It is a variant of the "classic" problem with polymorphic
0N/A // references in SML, which resulted in the usual array of
0N/A // fixes: notably value polymorphism.
0N/A
0N/A // This code compiles, but produces a ClassCastException
0N/A // when executed, even though there are no explicit casts in
0N/A // the program.
0N/A
0N/A public static void main (String [] args) {
0N/A Integer x = new Integer (5);
0N/A String y = castit (x);
0N/A System.out.println (y);
0N/A }
0N/A
0N/A static <A,B> A castit (B x) {
0N/A // This method casts any type to any other type.
0N/A // Oh dear. This shouldn't type check, but does
0N/A // because build () returns a type Ref<*>
0N/A // which is a subtype of RWRef<A,B>.
0N/A final RWRef<A,B> r = build ();
0N/A r.set (x);
0N/A return r.get ();
0N/A }
0N/A
0N/A static <A> Ref<A> build () {
0N/A return new Ref<A> ();
0N/A }
0N/A
0N/A // Another way of doing this is a variant of the crackit
0N/A // example discussed in the draft specification.
0N/A //
0N/A // The original duplicate was:
0N/A //
0N/A // static <A> Pair <A,A> duplicate (A x) {
0N/A // return new Pair<A,A> (x,x);
0N/A // }
0N/A //
0N/A // which breaks the requirement that a type variable
0N/A // instantiated by * only occurs once in the result type.
0N/A //
0N/A // However, we can achieve the same result with a different
0N/A // type for duplicate, which uses its type variables linearly
0N/A // in the result:
0N/A
0N/A static <A,B extends Ref<A>> Pair<Ref<A>,B> duplicate (B x) {
0N/A return new Pair<Ref<A>,B> (x,x);
0N/A }
0N/A
0N/A // the cheat here is that A and B are used linearly in the result
0N/A // type, but not in the polymorphic bounds.
0N/A
0N/A // We can use that to give an alternative implementation of
0N/A // castit.
0N/A
0N/A static <A,B> A castit2 (B x) {
0N/A Pair <Ref<A>, Ref<B>> p = duplicate (build ());
0N/A p.snd.set (x);
0N/A return p.fst.get ();
0N/A }
0N/A
0N/A
0N/A}
0N/A
0N/Ainterface RWRef<A,B> {
0N/A
0N/A public A get ();
0N/A public void set (B x);
0N/A
0N/A}
0N/A
0N/Aclass Ref<A> implements RWRef <A,A> {
0N/A
0N/A A contents;
0N/A
0N/A public void set (A x) { contents = x; }
0N/A public A get () { return contents; }
0N/A
0N/A}
0N/A
0N/Aclass Pair<A,B> {
0N/A
0N/A final A fst;
0N/A final B snd;
0N/A
0N/A Pair (A fst, B snd) { this.fst = fst; this.snd = snd; }
0N/A
0N/A}