Populate already inflated type instances with defined interfaces. Fixes #1389
authorMarek Safar <marek.safar@gmail.com>
Mon, 10 Oct 2011 17:39:42 +0000 (18:39 +0100)
committerMarek Safar <marek.safar@gmail.com>
Mon, 10 Oct 2011 17:41:08 +0000 (18:41 +0100)
mcs/mcs/class.cs
mcs/mcs/typespec.cs
mcs/tests/gtest-562.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

index d3dc57e2d916bef03924ba15487ca35e8a927ef2..4ccb423184bb038e290e25c8bf1d4a9c8b289c7f 100644 (file)
@@ -3,12 +3,13 @@
 //
 // Authors: Miguel de Icaza (miguel@gnu.org)
 //          Martin Baulig (martin@ximian.com)
-//          Marek Safar (marek.safar@seznam.cz)
+//          Marek Safar (marek.safar@gmail.com)
 //
 // Dual licensed under the terms of the MIT X11 or GNU GPL
 //
 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
 // Copyright 2004-2008 Novell, Inc
+// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
 //
 
 using System;
@@ -1223,7 +1224,7 @@ namespace Mono.CSharp
                                        if (iface_type == null)
                                                continue;
                                        
-                                       if (!spec.AddInterface (iface_type))
+                                       if (!spec.AddInterfaceDefined (iface_type))
                                                continue;
 
                                        TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
@@ -1239,7 +1240,7 @@ namespace Mono.CSharp
                                                var base_ifaces = new List<TypeSpec> (iface_type.Interfaces);
                                                for (int i = 0; i < base_ifaces.Count; ++i) {
                                                        var ii_iface_type = base_ifaces[i];
-                                                       if (spec.AddInterface (ii_iface_type)) {
+                                                       if (spec.AddInterfaceDefined (ii_iface_type)) {
                                                                TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ());
 
                                                                if (ii_iface_type.Interfaces != null)
index 5c8455224da04c730fcd2c80bec780b59ecd74b1..d25de6614b542229baafd2d26c9cc0fab0ca3fbe 100644 (file)
@@ -340,6 +340,34 @@ namespace Mono.CSharp
                        return false;
                }
 
+               //
+               // Special version used during type definition
+               //
+               public bool AddInterfaceDefined (TypeSpec iface)
+               {
+                       if (!AddInterface (iface))
+                               return false;
+
+                       //
+                       // We can get into a situation where a type is inflated before
+                       // its interfaces are resoved. Consider this situation
+                       //
+                       // class A<T> : X<A<int>>, IFoo {}
+                       //
+                       // When resolving base class of X`1 we inflate context type A`1
+                       // All this happens before we even hit IFoo resolve. Without
+                       // additional expansion any inside usage of A<T> would miss IFoo
+                       // interface because it comes from early inflated TypeSpec
+                       //
+                       if (inflated_instances != null) {
+                               foreach (var inflated in inflated_instances) {
+                                       inflated.Value.AddInterface (iface);
+                               }
+                       }
+
+                       return true;
+               }
+
                public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
                {
                        if (Kind != MemberKind.Class)
diff --git a/mcs/tests/gtest-562.cs b/mcs/tests/gtest-562.cs
new file mode 100644 (file)
index 0000000..9cd8d92
--- /dev/null
@@ -0,0 +1,56 @@
+interface IFoo { }
+
+abstract class A<T>
+{
+       public T Value;
+}
+
+class B<U> : A<B<U>>, IFoo
+{
+       public void Test ()
+       {
+               IFoo foo = this;
+               Value = this;
+       }
+}
+
+class C<U> : A<C<U>.N>, IFoo
+{
+       public void Test ()
+       {
+               IFoo foo = this;
+               Value = new N ();
+       }
+       
+       public class N
+       {
+       }
+}
+
+class D<U> : A<D<int>>
+{
+       public void Test ()
+       {
+               Value = new D<int> ();
+       }
+}
+
+class E<U> : IFoo where U : A<E<U>>
+{
+       public void Test (U u)
+       {
+               IFoo foo = u.Value;
+       }
+}
+
+static class Application
+{
+       public static int Main ()
+       {
+               new B<byte>().Test ();
+               new C<char>().Test ();
+               new D<string>().Test ();
+               
+               return 0;
+       }
+}
\ No newline at end of file
index f6f0f1f8a11cff61e8a05a79b013bedf8f5b6cc7..084c44582ea85a1838545a130b074b996c81488e 100644 (file)
       </method>
     </type>
   </test>
+  <test name="gtest-562.cs">
+    <type name="A`1[T]">
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="B`1[U]">
+      <method name="Void Test()">
+        <size>10</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="C`1[U]">
+      <method name="Void Test()">
+        <size>14</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="C`1+N[U]">
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="D`1[U]">
+      <method name="Void Test()">
+        <size>12</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="Application">
+      <method name="Int32 Main()">
+        <size>32</size>
+      </method>
+    </type>
+    <type name="E`1[U]">
+      <method name="Void Test(U)">
+        <size>13</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="gtest-anon-type-12.cs">
     <type name="C">
       <method name="Int32 Main()">