More work on ambiguous named arguments
authorMarek Safar <marek.safar@gmail.com>
Wed, 20 Oct 2010 08:09:22 +0000 (09:09 +0100)
committerMarek Safar <marek.safar@gmail.com>
Wed, 20 Oct 2010 08:11:00 +0000 (09:11 +0100)
mcs/errors/cs0121-13.cs [new file with mode: 0644]
mcs/errors/cs0121-14.cs [new file with mode: 0644]
mcs/errors/cs0121-15.cs [new file with mode: 0644]
mcs/mcs/ecore.cs
mcs/tests/test-named-06.cs [new file with mode: 0644]
mcs/tests/ver-il-dmcs.xml
mcs/tests/ver-il-gmcs.xml

diff --git a/mcs/errors/cs0121-13.cs b/mcs/errors/cs0121-13.cs
new file mode 100644 (file)
index 0000000..0d33c83
--- /dev/null
@@ -0,0 +1,19 @@
+// CS0121: The call is ambiguous between the following methods or properties: `C.Foo(int, long, params string[])' and `C.Foo(long, int, params string[])'
+// Line: 9
+
+class C
+{
+       public static void Main ()
+       {
+               var d = new C ();
+               d.Foo (b: 1, x: "", a : 2);
+       }
+
+       public void Foo (int a, long b, params string[] x)
+       {
+       }
+
+       public void Foo (long b, int a, params string[] x)
+       {
+       }
+}
diff --git a/mcs/errors/cs0121-14.cs b/mcs/errors/cs0121-14.cs
new file mode 100644 (file)
index 0000000..9578030
--- /dev/null
@@ -0,0 +1,19 @@
+// CS0121: The call is ambiguous between the following methods or properties: `C.Foo(int, params string[])' and `C.Foo(string[], int)'
+// Line: 9
+
+class C
+{
+       public static void Main ()
+       {
+               var d = new C ();
+               d.Foo (x: 1, y: new [] { "" });
+       }
+
+       public void Foo (int x, params string[] y)
+       {
+       }
+
+       public void Foo (string[] y, int x)
+       {
+       }
+}
diff --git a/mcs/errors/cs0121-15.cs b/mcs/errors/cs0121-15.cs
new file mode 100644 (file)
index 0000000..ccef7a6
--- /dev/null
@@ -0,0 +1,29 @@
+// CS0121: The call is ambiguous between the following methods or properties: `A.Foo(int, string)' and `A.Foo(string, int)'
+// Line: 27
+
+class A
+{
+       public virtual void Foo (int a2, string b2)
+       {
+       }
+       
+       public void Foo (string b, int a)
+       {
+       }
+}
+
+class B : A
+{
+       public override void Foo (int a, string b)
+       {
+       }
+}
+
+class C
+{
+       public static void Main ()
+       {
+               B b = new B ();
+               b.Foo (a: 1, b: "x");
+       }
+}
index a312c35864bd82509699459aa601d31fa5fab3ef..98f67001bbdb2c3eb2a52aeb9d28bb82418cd977 100644 (file)
@@ -3228,10 +3228,12 @@ namespace Mono.CSharp {
                {
                        public readonly MemberSpec Member;
                        public readonly bool Expanded;
+                       public readonly AParametersCollection Parameters;
 
-                       public AmbiguousCandidate (MemberSpec member, bool expanded)
+                       public AmbiguousCandidate (MemberSpec member, AParametersCollection parameters, bool expanded)
                        {
                                Member = member;
+                               Parameters = parameters;
                                Expanded = expanded;
                        }
                }
@@ -3430,8 +3432,8 @@ namespace Mono.CSharp {
                ///     false if candidate ain't better
                ///     true  if candidate is better than the current best match
                /// </remarks>
-               static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, bool candidate_params,
-                       MemberSpec best, bool best_params)
+               static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, AParametersCollection cparam, bool candidate_params,
+                       MemberSpec best, AParametersCollection bparam, bool best_params)
                {
                        AParametersCollection candidate_pd = ((IParametersMember) candidate).Parameters;
                        AParametersCollection best_pd = ((IParametersMember) best).Parameters;
@@ -3440,6 +3442,7 @@ namespace Mono.CSharp {
                        bool same = true;
                        int args_count = args == null ? 0 : args.Count;
                        int j = 0;
+                       TypeSpec ct, bt;
                        for (int c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) {
                                Argument a = args[j];
 
@@ -3447,17 +3450,34 @@ namespace Mono.CSharp {
                                if (a.IsDefaultArgument)
                                        break;
 
-                               TypeSpec ct = candidate_pd.Types[c_idx];
-                               TypeSpec bt = best_pd.Types[b_idx];
+                               //
+                               // When comparing named argument the parameter type index has to be looked up
+                               // in original parameter set (override version for virtual members)
+                               //
+                               NamedArgument na = a as NamedArgument;
+                               if (na != null) {
+                                       int idx = cparam.GetParameterIndexByName (na.Name);
+                                       ct = candidate_pd.Types[idx];
+                                       if (candidate_params && candidate_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS)
+                                               ct = TypeManager.GetElementType (ct);
+
+                                       idx = bparam.GetParameterIndexByName (na.Name);
+                                       bt = best_pd.Types[idx];
+                                       if (best_params && best_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS)
+                                               bt = TypeManager.GetElementType (bt);
+                               } else {
+                                       ct = candidate_pd.Types[c_idx];
+                                       bt = best_pd.Types[b_idx];
 
-                               if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) {
-                                       ct = TypeManager.GetElementType (ct);
-                                       --c_idx;
-                               }
+                                       if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) {
+                                               ct = TypeManager.GetElementType (ct);
+                                               --c_idx;
+                                       }
 
-                               if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) {
-                                       bt = TypeManager.GetElementType (bt);
-                                       --b_idx;
+                                       if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) {
+                                               bt = TypeManager.GetElementType (bt);
+                                               --b_idx;
+                                       }
                                }
 
                                if (ct == bt)
@@ -3505,6 +3525,7 @@ namespace Mono.CSharp {
                        // Prefer non-optional version
                        //
                        // LAMESPEC: Specification claims this should be done at last but the opposite is true
+                       //
                        if (candidate_params == best_params && candidate_pd.Count != best_pd.Count) {
                                if (candidate_pd.Count >= best_pd.Count)
                                        return false;
@@ -3550,8 +3571,15 @@ namespace Mono.CSharp {
 
                        bool specific_at_least_once = false;
                        for (j = 0; j < candidate_param_count; ++j) {
-                               var ct = candidate_def_pd.Types[j];
-                               var bt = best_def_pd.Types[j];
+                               NamedArgument na = args_count == 0 ? null : args [j] as NamedArgument;
+                               if (na != null) {
+                                       ct = candidate_def_pd.Types[cparam.GetParameterIndexByName (na.Name)];
+                                       bt = best_def_pd.Types[bparam.GetParameterIndexByName (na.Name)];
+                               } else {
+                                       ct = candidate_def_pd.Types[j];
+                                       bt = best_def_pd.Types[j];
+                               }
+
                                if (ct == bt)
                                        continue;
                                TypeSpec specific = MoreSpecific (ct, bt);
@@ -4053,7 +4081,7 @@ namespace Mono.CSharp {
                                                                }
 
                                                                // Is the new candidate better
-                                                               if (BetterFunction (rc, candidate_args, member, params_expanded_form, best_candidate, best_candidate_params)) {
+                                                               if (BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params)) {
                                                                        best_candidate = member;
                                                                        best_candidate_args = candidate_args;
                                                                        best_candidate_params = params_expanded_form;
@@ -4064,7 +4092,7 @@ namespace Mono.CSharp {
                                                                        if (ambiguous_candidates == null)
                                                                                ambiguous_candidates = new List<AmbiguousCandidate> ();
 
-                                                                       ambiguous_candidates.Add (new AmbiguousCandidate (member, params_expanded_form));
+                                                                       ambiguous_candidates.Add (new AmbiguousCandidate (member, pm.Parameters, params_expanded_form));
                                                                }
                                                        }
 
@@ -4136,7 +4164,7 @@ namespace Mono.CSharp {
                                for (int ix = 0; ix < ambiguous_candidates.Count; ix++) {
                                        var candidate = ambiguous_candidates [ix];
 
-                                       if (!BetterFunction (rc, candidate_args, best_candidate, best_candidate_params, candidate.Member, candidate.Expanded)) {
+                                       if (!BetterFunction (rc, candidate_args, best_candidate, best_parameter_member.Parameters, best_candidate_params, candidate.Member, candidate.Parameters, candidate.Expanded)) {
                                                var ambiguous = candidate.Member;
                                                if (custom_errors == null || !custom_errors.AmbiguousCandidates (rc, best_candidate, ambiguous)) {
                                                        rc.Report.SymbolRelatedToPreviousError (best_candidate);
diff --git a/mcs/tests/test-named-06.cs b/mcs/tests/test-named-06.cs
new file mode 100644 (file)
index 0000000..773d369
--- /dev/null
@@ -0,0 +1,26 @@
+class C
+{
+       public static int Main ()
+       {
+               var d = new C ();
+               if (d.Foo (x: 1, y : 2) != 3)
+                       return 1;
+               
+               return 0;
+       }
+
+       public int Foo (int x, long y, string a = "a")
+       {
+               return 1;
+       }
+
+       public int Foo (int x, long y, params string[] args)
+       {
+               return 2;
+       }
+
+       public int Foo (long y, int x)
+       {
+               return 3;
+       }
+}
index d43631c72e258b97df368eddb01557e371cf17bb..6ea89868af79ab86a4ffa9a64e6f64811722fda5 100644 (file)
       </method>
     </type>
   </test>
+  <test name="dtest-optional-01.cs">
+    <type name="G`1[T]">
+      <method name="System.Object M1(T)">
+        <size>7</size>
+      </method>
+      <method name="System.Object M2(T)">
+        <size>7</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="C">
+      <method name="System.Object Test(System.Object)">
+        <size>2</size>
+      </method>
+      <method name="Void TestS(S)">
+        <size>1</size>
+      </method>
+      <method name="System.Object TestD(System.Object)">
+        <size>2</size>
+      </method>
+      <method name="Int32 Main()">
+        <size>854</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="gtest-001.cs">
     <type name="Stack`1[type]">
       <method name="Void .ctor()">
         <size>2</size>
       </method>
       <method name="Int32 Main()">
-        <size>90</size>
+        <size>211</size>
       </method>
       <method name="Void .ctor()">
         <size>7</size>
       </method>
     </type>
   </test>
+  <test name="test-named-06.cs">
+    <type name="C">
+      <method name="Int32 Main()">
+        <size>25</size>
+      </method>
+      <method name="Int32 Foo(Int32, Int64, System.String)">
+        <size>2</size>
+      </method>
+      <method name="Int32 Foo(Int32, Int64, System.String[])">
+        <size>2</size>
+      </method>
+      <method name="Int32 Foo(Int64, Int32)">
+        <size>2</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-partial-01.cs">
     <type name="Foo.Hello">
       <method name="Void .ctor()">
index b4c9de5f6fb5bc15b8ddb0042a8759a0dfd7206f..91f184a96b0d20592364589cd8fd3fdea4a6dcc1 100644 (file)
         <size>2</size>
       </method>
       <method name="Int32 Main()">
-        <size>90</size>
+        <size>211</size>
       </method>
       <method name="Void .ctor()">
         <size>7</size>
       </method>
     </type>
   </test>
+  <test name="test-named-06.cs">
+    <type name="C">
+      <method name="Int32 Main()">
+        <size>25</size>
+      </method>
+      <method name="Int32 Foo(Int32, Int64, System.String)">
+        <size>2</size>
+      </method>
+      <method name="Int32 Foo(Int32, Int64, System.String[])">
+        <size>2</size>
+      </method>
+      <method name="Int32 Foo(Int64, Int32)">
+        <size>2</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-partial-01.cs">
     <type name="Foo.Hello">
       <method name="Void .ctor()">