Fixed moving of named params arguments
authorMarek Safar <marek.safar@gmail.com>
Mon, 23 Aug 2010 12:45:53 +0000 (13:45 +0100)
committerMarek Safar <marek.safar@gmail.com>
Mon, 23 Aug 2010 14:18:31 +0000 (15:18 +0100)
mcs/errors/cs1744.cs
mcs/mcs/ecore.cs
mcs/tests/gtest-named-03.cs [new file with mode: 0644]
mcs/tests/gtest-optional-12.cs [new file with mode: 0644]
mcs/tests/ver-il-gmcs.xml

index 14d1f7ca208c816a3be2c19bbe7143687d88526e..a3b3a32e6e360270488e19bbb4ab78ac2e34fab5 100644 (file)
@@ -1,6 +1,5 @@
 // CS1744: Named argument `a' cannot be used for a parameter which has positional argument specified
 // Line: 12
-// Compiler options: -langversion:future
 
 static class C
 {
index bc086cd7ac32350032bc0ed0664668fec2964f63..8f85a7e04c0ca5eff74ed85ced0b506965616463 100644 (file)
@@ -3533,6 +3533,7 @@ namespace Mono.CSharp {
                        AParametersCollection pd = ((IParametersMember) candidate).Parameters;
                        int param_count = pd.Count;
                        int optional_count = 0;
+                       int score;
 
                        if (arg_count != param_count) {
                                for (int i = 0; i < pd.Count; ++i) {
@@ -3562,22 +3563,19 @@ namespace Mono.CSharp {
                                                return int.MaxValue - 10000 + args_gap;
                                }
 
-                               // Initialize expanded form of a method with 1 params parameter
-                               params_expanded_form = param_count == 1 && pd.HasParams;
-
                                // Resize to fit optional arguments
                                if (optional_count != 0) {
-                                       Arguments resized;
                                        if (arguments == null) {
-                                               resized = new Arguments (optional_count);
+                                               arguments = new Arguments (optional_count);
                                        } else {
-                                               resized = new Arguments (param_count);
+                                               // Have to create a new container, so the next run can do same
+                                               var resized = new Arguments (param_count);
                                                resized.AddRange (arguments);
+                                               arguments = resized;
                                        }
 
                                        for (int i = arg_count; i < param_count; ++i)
-                                               resized.Add (null);
-                                       arguments = resized;
+                                               arguments.Add (null);
                                }
                        }
 
@@ -3598,19 +3596,31 @@ namespace Mono.CSharp {
                                                        int index = pd.GetParameterIndexByName (na.Name);
 
                                                        // Named parameter not found or already reordered
-                                                       if (index <= i)
+                                                       if (index == i || index < 0)
                                                                break;
 
-                                                       // When using parameters which should not be available to the user
-                                                       if (index >= param_count)
-                                                               break;
+                                                       Argument temp;
+                                                       if (index >= param_count) {
+                                                               // When using parameters which should not be available to the user
+                                                               if ((pd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0)
+                                                                       break;
+
+                                                               arguments.Add (null);
+                                                               ++arg_count;
+                                                               temp = null;
+                                                       } else {
+                                                               temp = arguments[index];
+
+                                                               // The slot has been taken by positional argument
+                                                               if (temp != null && !(temp is NamedArgument))
+                                                                       break;
+                                                       }
 
                                                        if (!arg_moved) {
                                                                arguments.MarkReorderedArgument (na);
                                                                arg_moved = true;
                                                        }
 
-                                                       Argument temp = arguments[index];
                                                        arguments[index] = arguments[i];
                                                        arguments[i] = temp;
 
@@ -3645,7 +3655,7 @@ namespace Mono.CSharp {
                                                prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs);
                                        }
 
-                                       int score = TypeManager.InferTypeArguments (ec, arguments, ref ms);
+                                       score = TypeManager.InferTypeArguments (ec, arguments, ref ms);
                                        lambda_conv_msgs.EndSession ();
 
                                        if (score != 0)
@@ -3696,12 +3706,15 @@ namespace Mono.CSharp {
                                if (p_mod != Parameter.Modifier.PARAMS) {
                                        p_mod = pd.FixedParameters[i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
                                        pt = pd.Types[i];
-                               } else {
+                               } else if (!params_expanded_form) {
                                        params_expanded_form = true;
+                                       pt = ((ElementTypeSpec) pt).Element;
+                                       i -= 2;
+                                       continue;
                                }
 
                                Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
-                               int score = 1;
+                               score = 1;
                                if (!params_expanded_form)
                                        score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
 
@@ -3709,7 +3722,10 @@ namespace Mono.CSharp {
                                // It can be applicable in expanded form (when not doing exact match like for delegates)
                                //
                                if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && (restrictions & Restrictions.CovariantDelegate) == 0) {
-                                       score = IsArgumentCompatible (ec, a_mod, a, 0, TypeManager.GetElementType (pt));
+                                       if (!params_expanded_form)
+                                               pt = ((ElementTypeSpec) pt).Element;
+
+                                       score = IsArgumentCompatible (ec, a_mod, a, 0, pt);
                                        if (score == 0)
                                                params_expanded_form = true;
                                }
@@ -3721,7 +3737,10 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (arg_count != pd.Count)
+                       //
+                       // When params parameter has notargument, will be provided later if the method is the best candidate
+                       //
+                       if (arg_count + 1 == pd.Count && (pd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0)
                                params_expanded_form = true;
 
                        return 0;
diff --git a/mcs/tests/gtest-named-03.cs b/mcs/tests/gtest-named-03.cs
new file mode 100644 (file)
index 0000000..144a33b
--- /dev/null
@@ -0,0 +1,20 @@
+using System;
+
+public class C
+{
+       static int Foo (int a, int b = 1, int c = 1)
+       {
+               return a;
+       }
+
+       public static int Main ()
+       {
+               if (Foo (c: 5, a: 10) != 10)
+                       return 1;
+
+               if (Foo (a: 10) != 10)
+                       return 2;
+
+               return 0;
+       }
+}
diff --git a/mcs/tests/gtest-optional-12.cs b/mcs/tests/gtest-optional-12.cs
new file mode 100644 (file)
index 0000000..f08e34b
--- /dev/null
@@ -0,0 +1,17 @@
+using System;
+
+public class C
+{
+       static int M (string s = "s", int k = 0, params int[] args)
+       {
+               return args[1];
+       }
+
+       public static int Main ()
+       {
+               if (M (args: new int[] { 10, 20, 30 }) != 20)
+                       return 1;
+
+               return 0;
+       }
+}
index 1f289853dff07a77f586bea61bbd547e7ffac9cf..a65a5824f73dc7ec8642b58019e665ff700f0d2e 100644 (file)
       </method>
     </type>
   </test>
+  <test name="gtest-named-03.cs">
+    <type name="C">
+      <method name="Int32 Foo(Int32, Int32, Int32)">
+        <size>2</size>
+      </method>
+      <method name="Int32 Main()">
+        <size>38</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="gtest-optional-01.cs">
     <type name="C">
       <method name="Void TestA(Int32)">
       </method>
     </type>
   </test>
+  <test name="gtest-optional-12.cs">
+    <type name="C">
+      <method name="Int32 M(System.String, Int32, System.Int32[])">
+        <size>4</size>
+      </method>
+      <method name="Int32 Main()">
+        <size>41</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="&lt;PrivateImplementationDetails&gt;">
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="gtest-partial-01.cs">
     <type name="B`1[U]">
       <method name="Void .ctor()">