[mcs] Method group caching needs to consider type arguments as well. Fixes #17059
authorMarek Safar <marek.safar@gmail.com>
Mon, 6 Jan 2014 10:07:35 +0000 (11:07 +0100)
committerMarek Safar <marek.safar@gmail.com>
Mon, 6 Jan 2014 10:10:09 +0000 (11:10 +0100)
mcs/mcs/delegate.cs
mcs/tests/gtest-602.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

index 569083e87ccfa8a0f5f85865dd3701dd9a52ee38..21854b19ff051685338f18527b18627c8eef8c82 100644 (file)
@@ -681,6 +681,25 @@ namespace Mono.CSharp {
 
                        return false;
                }
+               
+               bool HasMvar ()
+               {
+                       if (ContainsMethodTypeParameter (type))
+                               return false;
+
+                       var best = method_group.BestCandidate;
+                       if (ContainsMethodTypeParameter (best.DeclaringType))
+                               return false;
+
+                       if (best.TypeArguments != null) {
+                               foreach (var ta in best.TypeArguments) {
+                                       if (ContainsMethodTypeParameter (ta))
+                                               return false;
+                               }
+                       }
+
+                       return true;
+               }
 
                protected override Expression DoResolve (ResolveContext ec)
                {
@@ -700,10 +719,7 @@ namespace Mono.CSharp {
                        //
                        // Cannot easily cache types with MVAR
                        //
-                       if (ContainsMethodTypeParameter (type))
-                               return expr;
-
-                       if (ContainsMethodTypeParameter (method_group.BestCandidate.DeclaringType))
+                       if (!HasMvar ())
                                return expr;
 
                        //
diff --git a/mcs/tests/gtest-602.cs b/mcs/tests/gtest-602.cs
new file mode 100644 (file)
index 0000000..87ae360
--- /dev/null
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using System;
+
+public class Factory<TKey, TBase>
+{
+       delegate T InstantiateMethod<T> ();
+
+       Dictionary<TKey, InstantiateMethod<TBase>> _Products = new Dictionary<TKey, InstantiateMethod<TBase>> ();
+
+       public void Register<T> (TKey key) where T : TBase, new()
+       {
+               _Products.Add (key, Constructor<T>);
+       }
+
+       public TBase Produce (TKey key)
+       {
+               return _Products [key] ();
+       }
+
+       static TBase Constructor<T> () where T : TBase, new()
+       {
+               return new T ();
+       }
+}
+
+class BaseClass
+{
+}
+
+class ChildClass1 : BaseClass
+{
+}
+
+class ChildClass2 : BaseClass
+{
+}
+
+class TestClass
+{
+       public static int Main ()
+       {
+               var factory = new Factory<byte, BaseClass> ();
+               factory.Register<ChildClass1> (1);
+               factory.Register<ChildClass2> (2);
+
+               if (factory.Produce (1).GetType () != typeof (ChildClass1))
+                       return 1;
+
+               if (factory.Produce (2).GetType () != typeof (ChildClass2))
+                       return 2;
+
+               return 0;
+       }
+}
\ No newline at end of file
index 3aa0535f8b709e8c00f896ef17685d3c59568aae..77c12eecbf65f0636ef0b3a0f82e6dfafa3fc7a7 100644 (file)
       </method>\r
     </type>\r
   </test>\r
+  <test name="gtest-602.cs">\r
+    <type name="Factory`2[TKey,TBase]">\r
+      <method name="Void Register[T](TKey)" attrs="134">\r
+        <size>26</size>\r
+      </method>\r
+      <method name="TBase Produce(TKey)" attrs="134">\r
+        <size>26</size>\r
+      </method>\r
+      <method name="TBase Constructor[T]()" attrs="145">\r
+        <size>54</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>18</size>\r
+      </method>\r
+    </type>\r
+    <type name="Factory`2+InstantiateMethod`1[TKey,TBase,T]">\r
+      <method name="T Invoke()" attrs="454">\r
+        <size>0</size>\r
+      </method>\r
+      <method name="IAsyncResult BeginInvoke(System.AsyncCallback, System.Object)" attrs="454">\r
+        <size>0</size>\r
+      </method>\r
+      <method name="T EndInvoke(IAsyncResult)" attrs="454">\r
+        <size>0</size>\r
+      </method>\r
+      <method name="Void .ctor(Object, IntPtr)" attrs="6278">\r
+        <size>0</size>\r
+      </method>\r
+    </type>\r
+    <type name="BaseClass">\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+    <type name="ChildClass1">\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+    <type name="ChildClass2">\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+    <type name="TestClass">\r
+      <method name="Int32 Main()" attrs="150">\r
+        <size>108</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="gtest-anontype-01.cs">\r
     <type name="Test">\r
       <method name="Int32 Main()" attrs="150">\r