changeset 829:536ee9f126b1

5088429: varargs overloading problem Summary: compiler implementation for overload resolution w/ varargs method does not match JLS Reviewed-by: jjg
author mcimadamore
date Mon, 06 Dec 2010 11:51:02 +0000
parents 56f59723fddf
children 3c32c90031fd
files src/share/classes/com/sun/tools/javac/comp/Resolve.java test/tools/javac/varargs/5088429/T5088429Neg01.java test/tools/javac/varargs/5088429/T5088429Neg01.out test/tools/javac/varargs/5088429/T5088429Neg02.java test/tools/javac/varargs/5088429/T5088429Neg02.out test/tools/javac/varargs/5088429/T5088429Pos01.java test/tools/javac/varargs/5088429/T5088429Pos02.java
diffstat 7 files changed, 228 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Dec 06 11:50:37 2010 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Dec 06 11:51:02 2010 +0000
@@ -724,23 +724,11 @@
         switch (m2.kind) {
         case MTH:
             if (m1 == m2) return m1;
-            Type mt1 = types.memberType(site, m1);
-            noteWarner.unchecked = false;
-            boolean m1SignatureMoreSpecific =
-                (instantiate(env, site, m2, types.lowerBoundArgtypes(mt1), null,
-                             allowBoxing, false, noteWarner) != null ||
-                 useVarargs && instantiate(env, site, m2, types.lowerBoundArgtypes(mt1), null,
-                                           allowBoxing, true, noteWarner) != null) &&
-                !noteWarner.unchecked;
-            Type mt2 = types.memberType(site, m2);
-            noteWarner.unchecked = false;
-            boolean m2SignatureMoreSpecific =
-                (instantiate(env, site, m1, types.lowerBoundArgtypes(mt2), null,
-                             allowBoxing, false, noteWarner) != null ||
-                 useVarargs && instantiate(env, site, m1, types.lowerBoundArgtypes(mt2), null,
-                                           allowBoxing, true, noteWarner) != null) &&
-                !noteWarner.unchecked;
+            boolean m1SignatureMoreSpecific = signatureMoreSpecific(env, site, m1, m2, allowBoxing, useVarargs);
+            boolean m2SignatureMoreSpecific = signatureMoreSpecific(env, site, m2, m1, allowBoxing, useVarargs);
             if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
+                Type mt1 = types.memberType(site, m1);
+                Type mt2 = types.memberType(site, m2);
                 if (!types.overrideEquivalent(mt1, mt2))
                     return new AmbiguityError(m1, m2);
                 // same signature; select (a) the non-bridge method, or
@@ -824,6 +812,50 @@
             throw new AssertionError();
         }
     }
+    //where
+    private boolean signatureMoreSpecific(Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
+        Type mtype1 = types.memberType(site, adjustVarargs(m1, m2, useVarargs));
+        noteWarner.unchecked = false;
+        return (instantiate(env, site, adjustVarargs(m2, m1, useVarargs), types.lowerBoundArgtypes(mtype1), null,
+                             allowBoxing, false, noteWarner) != null ||
+                 useVarargs && instantiate(env, site, adjustVarargs(m2, m1, useVarargs), types.lowerBoundArgtypes(mtype1), null,
+                                           allowBoxing, true, noteWarner) != null) &&
+                !noteWarner.unchecked;
+    }
+    //where
+    private Symbol adjustVarargs(Symbol to, Symbol from, boolean useVarargs) {
+        List<Type> fromArgs = from.type.getParameterTypes();
+        List<Type> toArgs = to.type.getParameterTypes();
+        if (useVarargs &&
+                toArgs.length() < fromArgs.length() &&
+                (from.flags() & VARARGS) != 0 &&
+                (to.flags() & VARARGS) != 0) {
+            //if we are checking a varargs method 'from' against another varargs
+            //method 'to' (where arity of 'to' < arity of 'from') then expand signature
+            //of 'to' to 'fit' arity of 'from' (this means adding fake formals to 'to'
+            //until 'to' signature has the same arity as 'from')
+            ListBuffer<Type> args = ListBuffer.lb();
+            Type varargsTypeFrom = fromArgs.last();
+            Type varargsTypeTo = toArgs.last();
+            while (fromArgs.head != varargsTypeFrom) {
+                args.append(toArgs.head == varargsTypeTo ? types.elemtype(varargsTypeTo) : toArgs.head);
+                fromArgs = fromArgs.tail;
+                toArgs = toArgs.head == varargsTypeTo ?
+                    toArgs :
+                    toArgs.tail;
+            }
+            args.append(varargsTypeTo);
+            MethodSymbol msym = new MethodSymbol(to.flags_field,
+                                                 to.name,
+                                                 (Type)to.type.clone(), //see: 6990136
+                                                 to.owner);
+            MethodType mtype = msym.type.asMethodType();
+            mtype.argtypes = args.toList();
+            return msym;
+        } else {
+            return to;
+        }
+    }
 
     /** Find best qualified method matching given name, type and value
      *  arguments.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/varargs/5088429/T5088429Neg01.java	Mon Dec 06 11:51:02 2010 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5088429
+ *
+ * @summary varargs overloading problem
+ * @author mcimadamore
+ * @compile/fail/ref=T5088429Neg01.out -XDrawDiagnostics T5088429Neg01.java
+ *
+ */
+
+class T5088429Neg01 {
+    interface A {}
+    interface B extends A {}
+
+    T5088429Neg01(A... args) {}
+    T5088429Neg01(A a, A... args) {}
+
+    void test(B b) {
+        new T5088429Neg01(b);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/varargs/5088429/T5088429Neg01.out	Mon Dec 06 11:51:02 2010 +0000
@@ -0,0 +1,2 @@
+T5088429Neg01.java:42:9: compiler.err.ref.ambiguous: T5088429Neg01, kindname.constructor, T5088429Neg01(T5088429Neg01.A...), T5088429Neg01, kindname.constructor, T5088429Neg01(T5088429Neg01.A,T5088429Neg01.A...), T5088429Neg01
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/varargs/5088429/T5088429Neg02.java	Mon Dec 06 11:51:02 2010 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5088429
+ *
+ * @summary varargs overloading problem
+ * @author mcimadamore
+ * @compile/fail/ref=T5088429Neg02.out -XDrawDiagnostics T5088429Neg02.java
+ *
+ */
+
+class T5088429Neg02 {
+    interface A {}
+    interface B extends A {}
+
+    void m(A... args) {}
+    void m(A a, A... args) {}
+
+    void test(B b) {
+        m(b);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/varargs/5088429/T5088429Neg02.out	Mon Dec 06 11:51:02 2010 +0000
@@ -0,0 +1,2 @@
+T5088429Neg02.java:42:9: compiler.err.ref.ambiguous: m, kindname.method, m(T5088429Neg02.A...), T5088429Neg02, kindname.method, m(T5088429Neg02.A,T5088429Neg02.A...), T5088429Neg02
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/varargs/5088429/T5088429Pos01.java	Mon Dec 06 11:51:02 2010 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5088429
+ *
+ * @summary varargs overloading problem
+ * @author mcimadamore
+ * @compile T5088429Pos01.java
+ *
+ */
+
+class T5088429Pos01 {
+    interface A {}
+    interface B extends A {}
+
+    T5088429Pos01(A... args) {}
+    T5088429Pos01(B b, A... args) {}
+
+    void test(B b) {
+        new T5088429Pos01(b);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/varargs/5088429/T5088429Pos02.java	Mon Dec 06 11:51:02 2010 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5088429
+ *
+ * @summary varargs overloading problem
+ * @author mcimadamore
+ * @compile T5088429Pos02.java
+ *
+ */
+
+class T5088429Pos02 {
+    interface A {}
+    interface B extends A {}
+
+    void m(A... args) {}
+    void m(B b, A... args) {}
+
+    void test(B b) {
+        m(b);
+    }
+}