6315770: javac inference allows creation of strange types: Integer & Runnable
authormcimadamore
Thu, 29 Jan 2009 12:17:57 +0000
changeset 1991 aafb4bf914ee
parent 1990 5d90be5d60bb
child 1992 7be5dee022d5
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
langtools/src/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/test/tools/javac/generics/inference/6315770/T6315770.java
langtools/test/tools/javac/generics/inference/6315770/T6315770.out
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Tue Jan 27 18:38:39 2009 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Jan 29 12:17:57 2009 +0000
@@ -709,12 +709,31 @@
         case UNDETVAR:
             if (s.tag == WILDCARD) {
                 UndetVar undetvar = (UndetVar)t;
-                undetvar.inst = glb(upperBound(s), undetvar.inst);
-                // We should check instantiated type against any of the
-                // undetvar's lower bounds.
-                for (Type t2 : undetvar.lobounds) {
-                    if (!isSubtype(t2, undetvar.inst))
-                        return false;
+                WildcardType wt = (WildcardType)s;
+                switch(wt.kind) {
+                    case UNBOUND: //similar to ? extends Object
+                    case EXTENDS: {
+                        Type bound = upperBound(s);
+                        // We should check the new upper bound against any of the
+                        // undetvar's lower bounds.
+                        for (Type t2 : undetvar.lobounds) {
+                            if (!isSubtype(t2, bound))
+                                return false;
+                        }
+                        undetvar.hibounds = undetvar.hibounds.prepend(bound);
+                        break;
+                    }
+                    case SUPER: {
+                        Type bound = lowerBound(s);
+                        // We should check the new lower bound against any of the
+                        // undetvar's lower bounds.
+                        for (Type t2 : undetvar.hibounds) {
+                            if (!isSubtype(bound, t2))
+                                return false;
+                        }
+                        undetvar.lobounds = undetvar.lobounds.prepend(bound);
+                        break;
+                    }
                 }
                 return true;
             } else {
@@ -2825,6 +2844,16 @@
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Greatest lower bound">
+    public Type glb(List<Type> ts) {
+        Type t1 = ts.head;
+        for (Type t2 : ts.tail) {
+            if (t1.isErroneous())
+                return t1;
+            t1 = glb(t1, t2);
+        }
+        return t1;
+    }
+    //where
     public Type glb(Type t, Type s) {
         if (s == null)
             return t;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Jan 27 18:38:39 2009 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Jan 29 12:17:57 2009 +0000
@@ -154,33 +154,15 @@
                 that.inst = syms.objectType;
             else if (that.hibounds.tail.isEmpty())
                 that.inst = that.hibounds.head;
-            else {
-                for (List<Type> bs = that.hibounds;
-                     bs.nonEmpty() && that.inst == null;
-                     bs = bs.tail) {
-                    // System.out.println("hibounds = " + that.hibounds);//DEBUG
-                    if (isSubClass(bs.head, that.hibounds))
-                        that.inst = types.fromUnknownFun.apply(bs.head);
-                }
-                if (that.inst == null) {
-                    int classCount = 0, interfaceCount = 0;
-                    for (Type t : that.hibounds) {
-                        if (t.tag == CLASS) {
-                            if (t.isInterface())
-                                interfaceCount++;
-                            else
-                                classCount++;
-                        }
-                    }
-                    if ((that.hibounds.size() == classCount + interfaceCount) && classCount == 1)
-                        that.inst = types.makeCompoundType(that.hibounds);
-                }
-                if (that.inst == null || !types.isSubtypeUnchecked(that.inst, that.hibounds, warn))
-                    throw ambiguousNoInstanceException
-                        .setMessage("no.unique.maximal.instance.exists",
-                                    that.qtype, that.hibounds);
-            }
+            else
+                that.inst = types.glb(that.hibounds);
         }
+        if (that.inst == null ||
+            that.inst.isErroneous() ||
+            !types.isSubtypeUnchecked(that.inst, that.hibounds, warn))
+            throw ambiguousNoInstanceException
+                .setMessage("no.unique.maximal.instance.exists",
+                            that.qtype, that.hibounds);
     }
     //where
         private boolean isSubClass(Type t, final List<Type> ts) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/6315770/T6315770.java	Thu Jan 29 12:17:57 2009 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug     6315770
+ * @summary javac inference allows creation of strange types: Integer & Runnable
+ * @author Maurizio Cimadamore
+ *
+ * @compile/fail/ref=T6315770.out T6315770.java -XDrawDiagnostics
+ */
+
+class T6315770<V> {
+    <T extends Integer & Runnable> T6315770<T> m() {
+        return null;
+    }
+    void test() {
+        T6315770<?> c1 = m();
+        T6315770<? extends String> c2 = m();
+        T6315770<? super String> c3 = m();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/6315770/T6315770.out	Thu Jan 29 12:17:57 2009 +0000
@@ -0,0 +1,3 @@
+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)
+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>
+2 errors