//
// 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;
if (iface_type == null)
continue;
- if (!spec.AddInterface (iface_type))
+ if (!spec.AddInterfaceDefined (iface_type))
continue;
TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
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)
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)
--- /dev/null
+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
</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()">