[659038] Check interface hierarchy before reporting ambiguous errors
authorMarek Safar <marek.safar@gmail.com>
Mon, 13 Dec 2010 17:58:39 +0000 (17:58 +0000)
committerMarek Safar <marek.safar@gmail.com>
Mon, 13 Dec 2010 18:00:56 +0000 (18:00 +0000)
mcs/mcs/ecore.cs
mcs/tests/ver-il-gmcs.xml

index af877890043f9e7d81de70b00aafff078532cca3..44cf24a93f5c90c85306092efff115feb9632c32 100644 (file)
@@ -4175,8 +4175,39 @@ namespace Mono.CSharp {
                                                                                continue;
                                                                }
 
-                                                               // Is the new candidate better
-                                                               if (BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params)) {
+                                                               bool is_better;
+                                                               if (best_candidate.DeclaringType.IsInterface && member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) {
+                                                                       //
+                                                                       // We pack all interface members into top level type which makes the overload resolution
+                                                                       // more complicated for interfaces. We accomodate for this by removing methods with same
+                                                                       // signature when building the cache hence this path should not really be hit often
+                                                                       //
+                                                                       // Example:
+                                                                       // interface IA { void Foo (int arg); }
+                                                                       // interface IB : IA { void Foo (params int[] args); }
+                                                                       //
+                                                                       // IB::Foo is the best overload when calling IB.Foo (1)
+                                                                       //
+                                                                       is_better = true;
+                                                                       if (ambiguous_candidates != null) {
+                                                                               foreach (var amb_cand in ambiguous_candidates) {
+                                                                                       if (member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) {
+                                                                                               continue;
+                                                                                       }
+
+                                                                                       is_better = false;
+                                                                                       break;
+                                                                               }
+
+                                                                               if (is_better)
+                                                                                       ambiguous_candidates = null;
+                                                                       }
+                                                               } else {
+                                                                       // Is the new candidate better
+                                                                       is_better = BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params);
+                                                               }
+
+                                                               if (is_better) {
                                                                        best_candidate = member;
                                                                        best_candidate_args = candidate_args;
                                                                        best_candidate_params = params_expanded_form;
@@ -4253,6 +4284,33 @@ namespace Mono.CSharp {
                        }
 
                        if (ambiguous_candidates != null) {
+                               if (best_candidate.DeclaringType.IsInterface) {
+                                       ambiguous_candidates.Add (new AmbiguousCandidate (best_candidate, best_parameter_member.Parameters, best_candidate_params));
+                                       for (int cix = 0; cix < ambiguous_candidates.Count; ++cix) {
+                                               var tested_type = ambiguous_candidates[cix].Member.DeclaringType;
+
+                                               int ix = 0;
+                                               for (; ix < ambiguous_candidates.Count; ++ix) {
+                                                       var amb_cand_type = ambiguous_candidates[ix].Member.DeclaringType;
+                                                       if (amb_cand_type == tested_type)
+                                                               continue;
+
+                                                       if (tested_type.ImplementsInterface (amb_cand_type, false))
+                                                               continue;
+
+                                                       break;
+                                               }
+
+                                               if (ix != ambiguous_candidates.Count)
+                                                       continue;
+
+                                               best_candidate = ambiguous_candidates[cix].Member;
+                                               //best_parameter_member = ambiguous_candidates
+
+                                               throw new NotImplementedException ();
+                                       }
+                               }
+
                                //
                                // Now check that there are no ambiguities i.e the selected method
                                // should be better than all the others
index d143960413c308eea5e63842990762f184fd9214..9d62bef7467854c1b415ad2d2d5e6bd375347cc5 100644 (file)
       </method>
     </type>
   </test>
+  <test name="gtest-333.cs">
+    <type name="Program">
+      <method name="Void Main()">
+        <size>13</size>
+      </method>
+    </type>
+  </test>
   <test name="gtest-334.cs">
     <type name="Test">
       <method name="Void .ctor()">
       </method>
     </type>
   </test>
+  <test name="gtest-353.cs">
+    <type name="A`3[D1,D2,D3]">
+      <method name="Void Foo[T]()">
+        <size>1</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="B`1[DD2]">
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="C">
+      <method name="Void Foo[T]()">
+        <size>1</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="Program">
+      <method name="Void Main()">
+        <size>11</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
+  <test name="gtest-354.cs">
+    <type name="M">
+      <method name="Void IC.Method(System.Int32[])">
+        <size>1</size>
+      </method>
+      <method name="System.String IA&lt;string&gt;.Method(Int32)">
+        <size>6</size>
+      </method>
+      <method name="Void IB.Method(Int32)">
+        <size>6</size>
+      </method>
+      <method name="Void Main()">
+        <size>23</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="gtest-355.cs">
     <type name="A">
       <method name="Void .ctor()">
       </method>
     </type>
   </test>
-  <test name="test-679.cs">
-    <type name="Program">
-      <method name="Void .ctor()">
-        <size>7</size>
-      </method>
-      <method name="Int32 Main()">
-        <size>12</size>
-      </method>
-    </type>
-  </test>
   <test name="test-68.cs">
     <type name="Y">
       <method name="Void .ctor()">