6315770: javac inference allows creation of strange types: Integer & Runnable

Thu, 29 Jan 2009 12:17:57 +0000

author
mcimadamore
date
Thu, 29 Jan 2009 12:17:57 +0000
changeset 210
1aa81917016a
parent 209
9199b9092f73
child 211
4542977c959e

6315770: javac inference allows creation of strange types: Integer & Runnable
Summary: Javac does not apply glb correctly as per JLS3 15.12.2.8
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/Infer.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/6315770/T6315770.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/6315770/T6315770.out file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java	Tue Jan 27 18:38:39 2009 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Jan 29 12:17:57 2009 +0000
     1.3 @@ -709,12 +709,31 @@
     1.4          case UNDETVAR:
     1.5              if (s.tag == WILDCARD) {
     1.6                  UndetVar undetvar = (UndetVar)t;
     1.7 -                undetvar.inst = glb(upperBound(s), undetvar.inst);
     1.8 -                // We should check instantiated type against any of the
     1.9 -                // undetvar's lower bounds.
    1.10 -                for (Type t2 : undetvar.lobounds) {
    1.11 -                    if (!isSubtype(t2, undetvar.inst))
    1.12 -                        return false;
    1.13 +                WildcardType wt = (WildcardType)s;
    1.14 +                switch(wt.kind) {
    1.15 +                    case UNBOUND: //similar to ? extends Object
    1.16 +                    case EXTENDS: {
    1.17 +                        Type bound = upperBound(s);
    1.18 +                        // We should check the new upper bound against any of the
    1.19 +                        // undetvar's lower bounds.
    1.20 +                        for (Type t2 : undetvar.lobounds) {
    1.21 +                            if (!isSubtype(t2, bound))
    1.22 +                                return false;
    1.23 +                        }
    1.24 +                        undetvar.hibounds = undetvar.hibounds.prepend(bound);
    1.25 +                        break;
    1.26 +                    }
    1.27 +                    case SUPER: {
    1.28 +                        Type bound = lowerBound(s);
    1.29 +                        // We should check the new lower bound against any of the
    1.30 +                        // undetvar's lower bounds.
    1.31 +                        for (Type t2 : undetvar.hibounds) {
    1.32 +                            if (!isSubtype(bound, t2))
    1.33 +                                return false;
    1.34 +                        }
    1.35 +                        undetvar.lobounds = undetvar.lobounds.prepend(bound);
    1.36 +                        break;
    1.37 +                    }
    1.38                  }
    1.39                  return true;
    1.40              } else {
    1.41 @@ -2825,6 +2844,16 @@
    1.42      // </editor-fold>
    1.43  
    1.44      // <editor-fold defaultstate="collapsed" desc="Greatest lower bound">
    1.45 +    public Type glb(List<Type> ts) {
    1.46 +        Type t1 = ts.head;
    1.47 +        for (Type t2 : ts.tail) {
    1.48 +            if (t1.isErroneous())
    1.49 +                return t1;
    1.50 +            t1 = glb(t1, t2);
    1.51 +        }
    1.52 +        return t1;
    1.53 +    }
    1.54 +    //where
    1.55      public Type glb(Type t, Type s) {
    1.56          if (s == null)
    1.57              return t;
     2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Jan 27 18:38:39 2009 -0800
     2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Jan 29 12:17:57 2009 +0000
     2.3 @@ -154,33 +154,15 @@
     2.4                  that.inst = syms.objectType;
     2.5              else if (that.hibounds.tail.isEmpty())
     2.6                  that.inst = that.hibounds.head;
     2.7 -            else {
     2.8 -                for (List<Type> bs = that.hibounds;
     2.9 -                     bs.nonEmpty() && that.inst == null;
    2.10 -                     bs = bs.tail) {
    2.11 -                    // System.out.println("hibounds = " + that.hibounds);//DEBUG
    2.12 -                    if (isSubClass(bs.head, that.hibounds))
    2.13 -                        that.inst = types.fromUnknownFun.apply(bs.head);
    2.14 -                }
    2.15 -                if (that.inst == null) {
    2.16 -                    int classCount = 0, interfaceCount = 0;
    2.17 -                    for (Type t : that.hibounds) {
    2.18 -                        if (t.tag == CLASS) {
    2.19 -                            if (t.isInterface())
    2.20 -                                interfaceCount++;
    2.21 -                            else
    2.22 -                                classCount++;
    2.23 -                        }
    2.24 -                    }
    2.25 -                    if ((that.hibounds.size() == classCount + interfaceCount) && classCount == 1)
    2.26 -                        that.inst = types.makeCompoundType(that.hibounds);
    2.27 -                }
    2.28 -                if (that.inst == null || !types.isSubtypeUnchecked(that.inst, that.hibounds, warn))
    2.29 -                    throw ambiguousNoInstanceException
    2.30 -                        .setMessage("no.unique.maximal.instance.exists",
    2.31 -                                    that.qtype, that.hibounds);
    2.32 -            }
    2.33 +            else
    2.34 +                that.inst = types.glb(that.hibounds);
    2.35          }
    2.36 +        if (that.inst == null ||
    2.37 +            that.inst.isErroneous() ||
    2.38 +            !types.isSubtypeUnchecked(that.inst, that.hibounds, warn))
    2.39 +            throw ambiguousNoInstanceException
    2.40 +                .setMessage("no.unique.maximal.instance.exists",
    2.41 +                            that.qtype, that.hibounds);
    2.42      }
    2.43      //where
    2.44          private boolean isSubClass(Type t, final List<Type> ts) {
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/tools/javac/generics/inference/6315770/T6315770.java	Thu Jan 29 12:17:57 2009 +0000
     3.3 @@ -0,0 +1,42 @@
     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     6315770
    3.30 + * @summary javac inference allows creation of strange types: Integer & Runnable
    3.31 + * @author Maurizio Cimadamore
    3.32 + *
    3.33 + * @compile/fail/ref=T6315770.out T6315770.java -XDrawDiagnostics
    3.34 + */
    3.35 +
    3.36 +class T6315770<V> {
    3.37 +    <T extends Integer & Runnable> T6315770<T> m() {
    3.38 +        return null;
    3.39 +    }
    3.40 +    void test() {
    3.41 +        T6315770<?> c1 = m();
    3.42 +        T6315770<? extends String> c2 = m();
    3.43 +        T6315770<? super String> c3 = m();
    3.44 +    }
    3.45 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/tools/javac/generics/inference/6315770/T6315770.out	Thu Jan 29 12:17:57 2009 +0000
     4.3 @@ -0,0 +1,3 @@
     4.4 +T6315770.java:39:42: compiler.err.undetermined.type.1: <T>T6315770<T>, (- compiler.misc.no.unique.maximal.instance.exists: T, java.lang.String,java.lang.Integer,java.lang.Runnable)
     4.5 +T6315770.java:40:40: compiler.err.prob.found.req: (- compiler.misc.incompatible.types.1: (- compiler.misc.no.conforming.instance.exists: T, T6315770<T>, T6315770<? super java.lang.String>)), <T>T6315770<T>, T6315770<? super java.lang.String>
     4.6 +2 errors

mercurial