| author | Ayushman Jain | 2012-08-07 01:30:35 (EDT) |
|---|---|---|
| committer | Jayaprakash Arthanareeswaran | 2012-08-10 03:04:03 (EDT) |
| commit | 28a527aa646605138ee088f966d41bc12493ed40 (patch) (side-by-side diff) | |
| tree | 422eb7bcc638fbc322995ead17d64f693d089bf9 | |
| parent | 9119a1906c2bdf97ef9722a343397a64998ed131 (diff) | |
| download | eclipse.jdt.core-28a527aa646605138ee088f966d41bc12493ed40.zip eclipse.jdt.core-28a527aa646605138ee088f966d41bc12493ed40.tar.gz eclipse.jdt.core-28a527aa646605138ee088f966d41bc12493ed40.tar.bz2 | |
Fixed bug 383780: [compiler] Eclipse 4.2 creates ambiguous varargs
method error in 1.6 compliance mode (does not mimic JDK bug)
3 files changed, 450 insertions, 11 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java index 536723b..e2752d0 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2011 IBM Corporation and others. + * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -33,7 +33,7 @@ public class VarargsTest extends AbstractComparableTest { // Static initializer to specify tests subset using TESTS_* static variables // All specified tests which does not belong to the class are skipped... static { -// TESTS_NAMES = new String[] { "test000" }; +// TESTS_NAMES = new String[] { "test070b" }; // TESTS_NUMBERS = new int[] { 61 }; // TESTS_RANGE = new int[] { 11, -1 }; } @@ -798,6 +798,55 @@ public class VarargsTest extends AbstractComparableTest { "----------\n" ); } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=383780 + public void test015_tolerate() throws Exception { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; + Map options = getCompilerOptions(); + try { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "true"); + if (this.complianceLevel >= ClassFileConstants.JDK1_7) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void main(String[] s) {\n" + + " Y.count(new int[0]);\n" + // for some reason this is not ambiguous + " }\n" + + "}\n" + + "class Y {\n" + + " public static void count(int[] array, int ... values) { System.out.print(1); }\n" + + " public static void count(int[] array, int[] ... values) { System.out.print(2); }\n" + + "}\n", + }, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " Y.count(new int[0]);\n" + + " ^^^^^\n" + + "The method count(int[], int[]) is ambiguous for the type Y\n" + + "----------\n", + null, true, options); + } else { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void main(String[] s) {\n" + + " Y.count(new int[0]);\n" + // for some reason this is not ambiguous + " }\n" + + "}\n" + + "class Y {\n" + + " public static void count(int[] array, int ... values) { System.out.print(1); }\n" + + " public static void count(int[] array, int[] ... values) { System.out.print(2); }\n" + + "}\n", + }, + "1", + null, true, null, options, null); + } + } finally { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "false"); + } + } public void test016() { // check behaviour of Scope.mostSpecificMethodBinding() this.runNegativeTest( // but this call is ambiguous @@ -1235,7 +1284,7 @@ public class VarargsTest extends AbstractComparableTest { }, "1"); } - //https://bugs.eclipse.org/bugs/show_bug.cgi?id=102631 + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=102631 public void test033() { this.runNegativeTest( new String[] { @@ -1302,6 +1351,61 @@ public class VarargsTest extends AbstractComparableTest { "----------\n" ); } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=383780 + public void test033_tolerate() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; + Map options = getCompilerOptions(); + try { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "true"); + if (this.complianceLevel >= ClassFileConstants.JDK1_7) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " void a(boolean b, Object... o) {System.out.print(1);}\n" + + " void a(Object... o) {System.out.print(2);}\n" + + " public static void main(String[] args) {\n" + + " X x = new X();\n" + + " x.a(true);\n" + + " x.a(true, \"foobar\");\n" + + " x.a(\"foo\", \"bar\");\n" + + " }\n" + + "}\n", + }, + "----------\n" + + "1. ERROR in X.java (at line 6)\n" + + " x.a(true);\n" + + " ^\n" + + "The method a(boolean, Object[]) is ambiguous for the type X\n" + + "----------\n" + + "2. ERROR in X.java (at line 7)\n" + + " x.a(true, \"foobar\");\n" + + " ^\n" + + "The method a(boolean, Object[]) is ambiguous for the type X\n" + + "----------\n", + null, true, options); + } else { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void a(boolean b, Object... o) {System.out.print(1);}\n" + + " void a(Object... o) {System.out.print(2);}\n" + + " public static void main(String[] args) {\n" + + " X x = new X();\n" + + " x.a(true);\n" + + " x.a(true, \"foobar\");\n" + + " x.a(\"foo\", \"bar\");\n" + + " }\n" + + "}\n", + }, + "112", + null, true, null, options, null); + } + } finally { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "false"); + } + } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=106106 public void test034() { this.runConformTest( @@ -2818,6 +2922,106 @@ public class VarargsTest extends AbstractComparableTest { }, "Done"); } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=383780 + public void test070_tolerate() throws Exception { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; + Map options = getCompilerOptions(); + try { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "true"); + if (this.complianceLevel < ClassFileConstants.JDK1_7) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void foo(int ...i) {}\n" + + " public static void foo(double...d) {}\n" + + " public static void main(String[] args) {\n" + + " foo(1, 2, 3);\n" + + " System.out.println (\"Done\");\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " foo(1, 2, 3);\n" + + " ^^^\n" + + "The method foo(int[]) is ambiguous for the type X\n" + + "----------\n", + null, true, options); + } else { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void foo(int ...i) {}\n" + + " public static void foo(double...d) {}\n" + + " public static void main(String[] args) {\n" + + " foo(1, 2, 3);\n" + + " System.out.println (\"Done\");\n" + + " }\n" + + "}\n" + }, + "Done", + null, true, null, options, null); + } + } finally { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "false"); + } + + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=383780 + public void test070_tolerate2() throws Exception { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; + Map options = getCompilerOptions(); + try { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "true"); + if (this.complianceLevel >= ClassFileConstants.JDK1_7) { + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.Arrays;\n" + + "public class X {\n" + + " public static void test(int... a) {\n" + + " System.out.println(Arrays.toString(a));\n}\n" + + " public static <T> void test(Object... a) {\n" + + " System.out.println(Arrays.toString(a));\n}\n" + + " public static void main(String[] args) {\n" + + " test(1);\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 10)\n" + + " test(1);\n" + + " ^^^^\n" + + "The method test(int[]) is ambiguous for the type X\n" + + "----------\n", + null, true, options); + } else { + this.runConformTest( + new String[] { + "X.java", + "import java.util.Arrays;\n" + + "public class X {\n" + + " public static void test(int... a) {\n" + + " System.out.println(Arrays.toString(a));\n}\n" + + " public static <T> void test(Object... a) {\n" + + " System.out.println(Arrays.toString(a));\n}\n" + + " public static void main(String[] args) {\n" + + " test(1);\n" + + " }\n" + + "}\n" + }, + "[1]", + null, true, null, options, null); + } + } finally { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "false"); + } + + } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=346038 public void test070a() throws Exception { if (this.complianceLevel < ClassFileConstants.JDK1_5) return; @@ -2835,6 +3039,52 @@ public class VarargsTest extends AbstractComparableTest { }, "Done"); } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=383780 + public void test070a_tolerate() throws Exception { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; + Map options = getCompilerOptions(); + try { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "true"); + if (this.complianceLevel < ClassFileConstants.JDK1_7) { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public static <T> void foo(int ...i) {}\n" + + " public static <T> void foo(double...d) {}\n" + + " public static void main(String[] args) {\n" + + " foo(1, 2, 3);\n" + + " System.out.println (\"Done\");\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " foo(1, 2, 3);\n" + + " ^^^\n" + + "The method foo(int[]) is ambiguous for the type X\n" + + "----------\n", + null, true, options); + } else { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public static <T> void foo(int ...i) {}\n" + + " public static <T> void foo(double...d) {}\n" + + " public static void main(String[] args) {\n" + + " foo(1, 2, 3);\n" + + " System.out.println (\"Done\");\n" + + " }\n" + + "}\n" + }, + "Done", + null, true, null, options, null); + } + } finally { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "false"); + } + } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=346038 public void test070b() throws Exception { if (this.complianceLevel < ClassFileConstants.JDK1_5) return; @@ -2851,6 +3101,41 @@ public class VarargsTest extends AbstractComparableTest { }, ""); } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=383780 + public void test070b_tolerate() throws Exception { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; + String[] src = new String[] { + "X.java", + "public class X {\n" + + " public static void foo(int ...i) {}\n" + + " public static void foo(double d1, double...d) {}\n" + + " public static void main(String[] args) {\n" + + " foo(1, 2, 3); // foo NOT flagged ambiguous\n" + + " }\n" + + "}\n" + }; + try { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "true"); + if (this.complianceLevel >= ClassFileConstants.JDK1_7) { + this.runConformTest( + src, + ""); + } else { + this.runNegativeTest( + src, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " foo(1, 2, 3); // foo NOT flagged ambiguous\n" + + " ^^^\n" + + "The method foo(int[]) is ambiguous for the type X\n" + + "----------\n"); + } + } finally { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "false"); + } + } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=346038 public void test070c() { // check behaviour of Scope.mostSpecificMethodBinding() this.runNegativeTest( @@ -2935,6 +3220,48 @@ public class VarargsTest extends AbstractComparableTest { }, "1"); } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=383780 + public void test071_tolerate() throws Exception { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; + String[] src = + new String[] { + "X.java", + "public class X implements IClass{\n" + + " X(IClass c, X t, IType... args) {\n" + + " System.out.println (\"1\");\n" + + " }\n" + + " X(IClass c, IType... args) {\n" + + " System.out.println (\"2\");\n" + + " }\n" + + " public static void main(String args[]) {\n" + + " IClass c = null;\n" + + " X t = null;\n" + + " X t2 = new X(c, t); // incorrectly flagged ambiguous\n" + + " }\n" + + "}\n" + + "interface IType{}\n" + + "interface IClass extends IType{}\n" + }; + try { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "true"); + if (this.complianceLevel >= ClassFileConstants.JDK1_7) { + this.runConformTest( + src, + "1"); + } else { + this.runNegativeTest( + src, + "----------\n" + + "1. ERROR in X.java (at line 11)\n" + + " X t2 = new X(c, t); // incorrectly flagged ambiguous\n" + + " ^^^^^^^^^^^\n" + + "The constructor X(IClass, X, IType[]) is ambiguous\n" + + "----------\n"); + } + } finally { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "false"); + } + } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=364672 public void test072() { this.runConformTest( @@ -3010,4 +3337,87 @@ public class VarargsTest extends AbstractComparableTest { "The constructor B(A...) of type B is not applicable as the formal varargs element type A is not accessible here\n" + "----------\n"); } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=382469 + public void testBug382469() throws Exception { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; + String[] src = + new String[] { + "X.java", + "public class X {\n" + + " private static void bar(Object... objs) {\n" + + " System.out.println (\"1\");\n" + + " }\n" + + " private static void bar(int intValue, Object... objs) {\n" + + " System.out.println (\"2\");\n" + + " }\n" + + " public static void main(String args[]) {\n" + + " bar(5);\n" + + " }\n" + + "}\n" + }; + try { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "true"); + if (this.complianceLevel < ClassFileConstants.JDK1_7) { + this.runConformTest( + src, + "2"); + } else { + this.runNegativeTest( + src, + "----------\n" + + "1. WARNING in X.java (at line 5)\n" + + " private static void bar(int intValue, Object... objs) {\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "The method bar(int, Object...) from the type X is never used locally\n" + + "----------\n" + + "2. ERROR in X.java (at line 9)\n" + + " bar(5);\n" + + " ^^^\n" + + "The method bar(Object[]) is ambiguous for the type X\n" + + "----------\n"); + } + } finally { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "false"); + } + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=386361 + public void testBug386361() throws Exception { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; + String[] src = + new String[] { + "X.java", + "public class X {\n" + + " public static void test(int i, Object... objects) {\n" + + " System.out.println (\"1\");\n" + + " }\n" + + " public static void test(Object... objects) {\n" + + " System.out.println (\"2\");\n" + + " }\n" + + " public static void main(String args[]) {\n" + + " test(1,\"test\");\n" + + " }\n" + + "}\n" + }; + try { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "true"); + if (this.complianceLevel < ClassFileConstants.JDK1_7) { + this.runConformTest( + src, + "1"); + } else { + this.runNegativeTest( + src, + "----------\n" + + "1. ERROR in X.java (at line 9)\n" + + " test(1,\"test\");\n" + + " ^^^^\n" + + "The method test(int, Object[]) is ambiguous for the type X\n" + + "----------\n"); + } + } finally { + System.setProperty("tolerateIllegalAmbiguousVarargsInvocation", "false"); + } + } }
\ No newline at end of file diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java index ce3a678..101b6ab 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java @@ -419,6 +419,15 @@ public class CompilerOptions { public boolean analyseResourceLeaks; /** Should missing enum cases be reported even if a default case exists in the same switch? */ public boolean reportMissingEnumCaseDespiteDefault; + + /** Should the compiler tolerate illegal ambiguous varargs invocation in compliance < 1.7 + * to be bug compatible with javac? (bug 383780) */ + public static boolean tolerateIllegalAmbiguousVarargsInvocation; + + { + String tolerateIllegalAmbiguousVarargs = System.getProperty("tolerateIllegalAmbiguousVarargsInvocation"); //$NON-NLS-1$ + tolerateIllegalAmbiguousVarargsInvocation = tolerateIllegalAmbiguousVarargs != null && tolerateIllegalAmbiguousVarargs.equalsIgnoreCase("true"); //$NON-NLS-1$ + } // keep in sync with warningTokenToIrritant and warningTokenFromIrritant public final static String[] warningTokens = { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java index 9066874..3ee0355 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -556,9 +556,9 @@ public abstract class Scope { if (argLength != paramLength) if (!isVarArgs || argLength < paramLength - 1) return null; // incompatible - + CompilerOptions compilerOptions = this.compilerOptions(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=330435, inference should kick in only at source 1.5+ - if (typeVariables != Binding.NO_TYPE_VARIABLES && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { // generic method + if (typeVariables != Binding.NO_TYPE_VARIABLES && compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5) { // generic method TypeBinding[] newArgs = null; for (int i = 0; i < argLength; i++) { TypeBinding param = i < paramLength ? parameters[i] : parameters[paramLength - 1]; @@ -575,7 +575,7 @@ public abstract class Scope { method = ParameterizedGenericMethodBinding.computeCompatibleMethod(method, arguments, this, invocationSite); if (method == null) return null; // incompatible if (!method.isValidBinding()) return method; // bound check issue is taking precedence - } else if (genericTypeArguments != null && compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) { + } else if (genericTypeArguments != null && compilerOptions.complianceLevel < ClassFileConstants.JDK1_7) { if (method instanceof ParameterizedGenericMethodBinding) { if (!((ParameterizedGenericMethodBinding) method).wasInferred) // attempt to invoke generic method of raw type with type hints <String>foo() @@ -586,6 +586,10 @@ public abstract class Scope { } int compatibilityLevel; + if (tiebreakingVarargsMethods) { + if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && compilerOptions.complianceLevel < ClassFileConstants.JDK1_7) + tiebreakingVarargsMethods = false; + } if ((compatibilityLevel = parameterCompatibilityLevel(method, arguments, tiebreakingVarargsMethods)) > NOT_COMPATIBLE) { if (compatibilityLevel == VARARGS_COMPATIBLE) { TypeBinding varargsElementType = method.parameters[method.parameters.length - 1].leafComponentType(); @@ -3056,8 +3060,13 @@ public abstract class Scope { if (i == oneParamsLength - 1 && one.isVarargs() && two.isVarargs()) { TypeBinding oType = ((ArrayBinding) oneParam).elementsType(); TypeBinding eType = ((ArrayBinding) twoParam).elementsType(); - if (oType == eType || oType.isCompatibleWith(eType)) - return true; // special case to choose between 2 varargs methods when the last arg is Object[] + if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && this.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) { + if (oneParam == eType || oneParam.isCompatibleWith(eType)) + return true; // special case to choose between 2 varargs methods when the last arg is Object[] + } else { + if (oType == eType || oType.isCompatibleWith(eType)) + return true; // special case to choose between 2 varargs methods when the last arg is Object[] + } } return false; } @@ -3066,6 +3075,12 @@ public abstract class Scope { } if (one.isVarargs() && two.isVarargs()) { + if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && this.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7 && + oneParamsLength > twoParamsLength) { + // special case when autoboxing makes (int, int...) better than (Object...) but not (int...) or (Integer, int...) + if (((ArrayBinding) twoParams[twoParamsLength - 1]).elementsType().id != TypeIds.T_JavaLangObject) + return false; + } // check that each parameter before the vararg parameters are compatible (no autoboxing allowed here) for (int i = (oneParamsLength > twoParamsLength ? twoParamsLength : oneParamsLength) - 2; i >= 0; i--) if (oneParams[i] != twoParams[i] && !oneParams[i].isCompatibleWith(twoParams[i])) @@ -4050,7 +4065,8 @@ public abstract class Scope { int paramLength = parameters.length; int argLength = arguments.length; - if (compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) { + CompilerOptions compilerOptions = compilerOptions(); + if (compilerOptions.sourceLevel < ClassFileConstants.JDK1_5) { if (paramLength != argLength) return NOT_COMPATIBLE; for (int i = 0; i < argLength; i++) { @@ -4062,7 +4078,11 @@ public abstract class Scope { } return COMPATIBLE; } - + if (tiebreakingVarargsMethods) { + if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && compilerOptions.complianceLevel < ClassFileConstants.JDK1_7) { + tiebreakingVarargsMethods = false; + } + } int level = COMPATIBLE; // no autoboxing or varargs support needed int lastIndex = argLength; LookupEnvironment env = environment(); @@ -4119,7 +4139,7 @@ public abstract class Scope { // only called if env.options.sourceLevel >= ClassFileConstants.JDK1_5 if (arg.isCompatibleWith(param)) return COMPATIBLE; - if (tieBreakingVarargsMethods) { + if (tieBreakingVarargsMethods && (this.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_7 || !CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation)) { /* 15.12.2.5 Choosing the Most Specific Method, ... One variable arity member method named m is more specific than another variable arity member method of the same name if either ... Only subtypes relationship should be used. Actually this is true even for fixed arity methods, but in practice is not an issue since we run the algorithm |

