Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / mcs / typespec.cs
index 2eef4f276f8cf8958ad2583c2b26a2a475b7aab5..d1e1b709d1d17027443723e76bd265ae80133350 100644 (file)
@@ -6,18 +6,29 @@
 // Dual licensed under the terms of the MIT X11 or GNU GPL
 //
 // Copyright 2010 Novell, Inc
+// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
 //
 
 using System;
 using System.Collections.Generic;
 using System.Text;
+
+#if STATIC
+using MetaType = IKVM.Reflection.Type;
+using IKVM.Reflection;
+#else
+using MetaType = System.Type;
 using System.Reflection;
+#endif
 
 namespace Mono.CSharp
 {
+       //
+       // Inflated or non-inflated representation of any type. 
+       //
        public class TypeSpec : MemberSpec
        {
-               protected Type info;
+               protected MetaType info;
                protected MemberCache cache;
                protected IList<TypeSpec> ifaces;
                TypeSpec base_type;
@@ -26,6 +37,7 @@ namespace Mono.CSharp
 
                public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
 
+#if !STATIC
                // Reflection Emit hacking
                static readonly Type TypeBuilder;
                static readonly Type GenericTypeBuilder;
@@ -38,8 +50,9 @@ namespace Mono.CSharp
                        if (GenericTypeBuilder == null)
                                GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation");
                }
+#endif
 
-               public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, Type info, Modifiers modifiers)
+               public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, MetaType info, Modifiers modifiers)
                        : base (kind, declaringType, definition, modifiers)
                {
                        this.declaringType = declaringType;
@@ -66,9 +79,9 @@ namespace Mono.CSharp
                        }
                }
 
-               public virtual BuildinTypeSpec.Type BuildinType {
+               public virtual BuiltinTypeSpec.Type BuiltinType {
                        get {
-                               return BuildinTypeSpec.Type.None;
+                               return BuiltinTypeSpec.Type.None;
                        }
                }
 
@@ -100,11 +113,11 @@ namespace Mono.CSharp
 
                                var type = this;
                                do {
+                                       if (type.BuiltinType == BuiltinTypeSpec.Type.Attribute)
+                                               return true;
+
                                        if (type.IsGeneric)
                                                return false;
-
-                                       if (type == TypeManager.attribute_type)
-                                               return true;
                                        
                                        type = type.base_type;
                                } while (type != null);
@@ -130,7 +143,25 @@ namespace Mono.CSharp
                                if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
                                        return true;
 
-                               return TypeManager.IsPrimitiveType (this) || this == TypeManager.decimal_type || this == InternalType.Dynamic;
+                               switch (BuiltinType) {
+                               case BuiltinTypeSpec.Type.Int:
+                               case BuiltinTypeSpec.Type.UInt:
+                               case BuiltinTypeSpec.Type.Long:
+                               case BuiltinTypeSpec.Type.ULong:
+                               case BuiltinTypeSpec.Type.Float:
+                               case BuiltinTypeSpec.Type.Double:
+                               case BuiltinTypeSpec.Type.Char:
+                               case BuiltinTypeSpec.Type.Short:
+                               case BuiltinTypeSpec.Type.Decimal:
+                               case BuiltinTypeSpec.Type.Bool:
+                               case BuiltinTypeSpec.Type.SByte:
+                               case BuiltinTypeSpec.Type.Byte:
+                               case BuiltinTypeSpec.Type.UShort:
+                               case BuiltinTypeSpec.Type.Dynamic:
+                                       return true;
+                               }
+
+                               return false;
                        }
                }
 
@@ -140,8 +171,46 @@ namespace Mono.CSharp
                        }
                }
 
+               //
+               // Returns true for instances of Expression<T>
+               //
+               public virtual bool IsExpressionTreeType {
+                       get {
+                               return false;
+                       }
+                       set {
+                               state = value ? state | StateFlags.InflatedExpressionType : state & ~StateFlags.InflatedExpressionType;
+                       }
+               }
+
                public bool IsEnum {
-                       get { return Kind == MemberKind.Enum; }
+                       get {
+                               return Kind == MemberKind.Enum;
+                       }
+               }
+
+               //
+               // Returns true for instances of IList<T>, IEnumerable<T>, ICollection<T>
+               //
+               public virtual bool IsGenericIterateInterface {
+                       get {
+                               return false;
+                       }
+                       set {
+                               state = value ? state | StateFlags.GenericIterateInterface : state & ~StateFlags.GenericIterateInterface;
+                       }
+               }
+
+               //
+               // Returns true for instances of System.Threading.Tasks.Task<T>
+               //
+               public virtual bool IsGenericTask {
+                       get {
+                               return false;
+                       }
+                       set {
+                               state = value ? state | StateFlags.GenericTask : state & ~StateFlags.GenericTask;
+                       }
                }
 
                // TODO: Should probably do
@@ -161,7 +230,21 @@ namespace Mono.CSharp
                }
 
                public bool IsGenericParameter {
-                       get { return Kind == MemberKind.TypeParameter; }
+                       get {
+                               return Kind == MemberKind.TypeParameter;
+                       }
+               }
+
+               //
+               // Returns true for instances of Nullable<T>
+               //
+               public virtual bool IsNullableType {
+                       get {
+                               return false;
+                       }
+                       set {
+                               state = value ? state | StateFlags.InflatedNullableType : state & ~StateFlags.InflatedNullableType;
+                       }
                }
 
                public bool IsNested {
@@ -178,6 +261,15 @@ namespace Mono.CSharp
                        get { return (Modifiers & Modifiers.SEALED) != 0; }
                }
 
+               public bool IsSpecialRuntimeType {
+                       get {
+                               return (state & StateFlags.SpecialRuntimeType) != 0;
+                       }
+                       set {
+                               state = value ? state | StateFlags.SpecialRuntimeType : state & ~StateFlags.SpecialRuntimeType;
+                       }
+               }
+
                public bool IsStruct {
                        get { 
                                return Kind == MemberKind.Struct;
@@ -186,11 +278,40 @@ namespace Mono.CSharp
 
                public bool IsTypeBuilder {
                        get {
+#if STATIC
+                               return true;
+#else
                                var meta = GetMetaInfo().GetType ();
                                return meta == TypeBuilder || meta == GenericTypeBuilder;
+#endif
                        }
                }
 
+               //
+               // Whether a type is unmanaged. This is used by the unsafe code
+               //
+               public bool IsUnmanaged {
+                       get {
+                               if (IsPointer)
+                                       return ((ElementTypeSpec) this).Element.IsUnmanaged;
+
+                               var ds = MemberDefinition as TypeDefinition;
+                               if (ds != null)
+                                       return ds.IsUnmanagedType ();
+
+                               if (Kind == MemberKind.Void)
+                                       return true;
+
+                               if (IsNested && DeclaringType.IsGenericOrParentIsGeneric)
+                                       return false;
+
+                               return IsValueType (this);
+                       }
+               }
+
+               //
+               // A cache of all type members (including nested types)
+               //
                public MemberCache MemberCache {
                        get {
                                if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
@@ -247,6 +368,58 @@ 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;
+               }
+
+               //
+               // Returns all type arguments, usefull for nested types
+               //
+               public static TypeSpec[] GetAllTypeArguments (TypeSpec type)
+               {
+                       IList<TypeSpec> targs = TypeSpec.EmptyTypes;
+
+                       do {
+                               if (type.Arity > 0) {
+                                       if (targs.Count == 0) {
+                                               targs = type.TypeArguments;
+                                       } else {
+                                               var list = targs as List<TypeSpec> ?? new List<TypeSpec> (targs);
+                                               list.AddRange (type.TypeArguments);
+                                               targs = list;
+                                       }
+                               }
+
+                               type = type.declaringType;
+                       } while (type != null);
+
+                       return targs as TypeSpec[] ?? ((List<TypeSpec>) targs).ToArray ();
+               }
+
                public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
                {
                        if (Kind != MemberKind.Class)
@@ -268,7 +441,10 @@ namespace Mono.CSharp
                        return aua;
                }
 
-               public virtual Type GetMetaInfo ()
+               //
+               // Return metadata information used during emit to describe the type
+               //
+               public virtual MetaType GetMetaInfo ()
                {
                        return info;
                }
@@ -278,6 +454,68 @@ namespace Mono.CSharp
                        return this;
                }
 
+               //
+               // Text representation of type used by documentation writer
+               //
+               public override string GetSignatureForDocumentation ()
+               {
+                       StringBuilder sb = new StringBuilder ();
+                       if (IsNested) {
+                               sb.Append (DeclaringType.GetSignatureForDocumentation ());
+                       } else {
+                               sb.Append (MemberDefinition.Namespace);
+                       }
+
+                       if (sb.Length != 0)
+                               sb.Append (".");
+
+                       sb.Append (Name);
+                       if (Arity > 0) {
+                               if (this is InflatedTypeSpec) {
+                                   sb.Append ("{");
+                                   for (int i = 0; i < Arity; ++i) {
+                                       if (i > 0)
+                                           sb.Append (",");
+
+                                       sb.Append (TypeArguments[i].GetSignatureForDocumentation ());
+                                   }
+                                   sb.Append ("}");
+                               } else {
+                                       sb.Append ("`");
+                                       sb.Append (Arity.ToString ());
+                               }
+                       }
+
+                       return sb.ToString ();
+               }
+
+               public string GetExplicitNameSignatureForDocumentation ()
+               {
+                       StringBuilder sb = new StringBuilder ();
+                       if (IsNested) {
+                               sb.Append (DeclaringType.GetExplicitNameSignatureForDocumentation ());
+                       } else if (MemberDefinition.Namespace != null) {
+                               sb.Append (MemberDefinition.Namespace.Replace ('.', '#'));
+                       }
+
+                       if (sb.Length != 0)
+                               sb.Append ("#");
+
+                       sb.Append (Name);
+                       if (Arity > 0) {
+                               sb.Append ("{");
+                               for (int i = 0; i < Arity; ++i) {
+                                       if (i > 0)
+                                               sb.Append (",");
+
+                                       sb.Append (TypeArguments[i].GetExplicitNameSignatureForDocumentation ());
+                               }
+                               sb.Append ("}");
+                       }
+
+                       return sb.ToString ();
+               }
+
                public override string GetSignatureForError ()
                {
                        string s;
@@ -296,6 +534,11 @@ namespace Mono.CSharp
                        return s + Name + GetTypeNameSignature ();
                }
 
+               public string GetSignatureForErrorIncludingAssemblyName ()
+               {
+                       return string.Format ("{0} [{1}]", GetSignatureForError (), MemberDefinition.DeclaringAssembly.FullName);
+               }
+
                protected virtual string GetTypeNameSignature ()
                {
                        if (!IsGeneric)
@@ -308,16 +551,18 @@ namespace Mono.CSharp
                {
                        var t = this;
                        do {
-                               if (t.Interfaces != null) {     // TODO: Try t.iface
-                                       foreach (TypeSpec i in t.Interfaces) {
-                                               if (i == iface || TypeSpecComparer.IsEqual (i, iface))
+                               var ifaces = t.Interfaces;
+                               if (ifaces != null) {
+                                       for (int i = 0; i < ifaces.Count; ++i) {
+                                               if (TypeSpecComparer.IsEqual (ifaces[i], iface))
                                                        return true;
 
-                                               if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface))
+                                               if (variantly && TypeSpecComparer.Variant.IsEqual (ifaces[i], iface))
                                                        return true;
                                        }
                                }
 
+                               // TODO: Why is it needed when we do it during import
                                t = t.BaseType;
                        } while (t != null);
 
@@ -326,7 +571,11 @@ namespace Mono.CSharp
 
                protected virtual void InitializeMemberCache (bool onlyTypes)
                {
-                       MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
+                       try {
+                               MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
+                       } catch (Exception e) {
+                               throw new InternalErrorException (e, "Unexpected error when loading type `{0}'", GetSignatureForError ());
+                       }
 
                        if (onlyTypes)
                                state |= StateFlags.PendingMemberCacheMembers;
@@ -347,10 +596,12 @@ namespace Mono.CSharp
                                //
                                // class B : A<object> {}
                                //
+                               type = type.BaseType;
                                while (type != null) {
-                                       type = type.BaseType;
                                        if (TypeSpecComparer.IsEqual (type, baseClass))
                                                return true;
+
+                                       type = type.BaseType;
                                }
 
                                return false;
@@ -365,6 +616,38 @@ namespace Mono.CSharp
                        return false;
                }
 
+               public static bool IsReferenceType (TypeSpec t)
+               {
+                       switch (t.Kind) {
+                       case MemberKind.TypeParameter:
+                               return ((TypeParameterSpec) t).IsReferenceType;
+                       case MemberKind.Struct:
+                       case MemberKind.Enum:
+                       case MemberKind.Void:
+                               return false;
+                       case MemberKind.InternalCompilerType:
+                               //
+                               // Null is considered to be a reference type
+                               //                      
+                               return t == InternalType.NullLiteral || t.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
+                       default:
+                               return true;
+                       }
+               }
+
+               public static bool IsValueType (TypeSpec t)
+               {
+                       switch (t.Kind) {
+                       case MemberKind.TypeParameter:
+                               return ((TypeParameterSpec) t).IsValueType;
+                       case MemberKind.Struct:
+                       case MemberKind.Enum:
+                               return true;
+                       default:
+                               return false;
+                       }
+               }
+
                public override MemberSpec InflateMember (TypeParameterInflator inflator)
                {
                        var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
@@ -374,13 +657,16 @@ namespace Mono.CSharp
                        // because type parameters are same for all nested types
                        //
                        if (DeclaringType == inflator.TypeInstance) {
-                               return MakeGenericType (targs);
+                               return MakeGenericType (inflator.Context, targs);
                        }
 
-                       return new InflatedTypeSpec (this, inflator.TypeInstance, targs);
+                       return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs);
                }
 
-               public InflatedTypeSpec MakeGenericType (TypeSpec[] targs)
+               //
+               // Inflates current type using specific type arguments
+               //
+               public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs)
                {
                        if (targs.Length == 0 && !IsNested)
                                throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
@@ -408,7 +694,7 @@ namespace Mono.CSharp
                                        throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
                                                GetSignatureForError ());
 
-                               instance = new InflatedTypeSpec (this, declaringType, targs);
+                               instance = new InflatedTypeSpec (context, this, declaringType, targs);
                                inflated_instances.Add (targs, instance);
                        }
 
@@ -420,7 +706,55 @@ namespace Mono.CSharp
                        return this;
                }
 
-               public void SetMetaInfo (Type info)
+               public override List<TypeSpec> ResolveMissingDependencies ()
+               {
+                       List<TypeSpec> missing = null;
+
+                       if (Kind == MemberKind.MissingType) {
+                               missing = new List<TypeSpec> ();
+                               missing.Add (this);
+                               return missing;
+                       }
+
+                       foreach (var targ in TypeArguments) {
+                               if (targ.Kind == MemberKind.MissingType) {
+                                       if (missing == null)
+                                               missing = new List<TypeSpec> ();
+
+                                       missing.Add (targ);
+                               }
+                       }
+
+                       if (Interfaces != null) {
+                               foreach (var iface in Interfaces) {
+                                       if (iface.Kind == MemberKind.MissingType) {
+                                               if (missing == null)
+                                                       missing = new List<TypeSpec> ();
+
+                                               missing.Add (iface);
+                                       }
+                               }
+                       }
+
+                       if (MemberDefinition.TypeParametersCount > 0) {
+                               foreach (var tp in MemberDefinition.TypeParameters) {
+                                       var tp_missing = tp.GetMissingDependencies ();
+                                       if (tp_missing != null) {
+                                               if (missing == null)
+                                                       missing = new List<TypeSpec> ();
+
+                                               missing.AddRange (tp_missing);
+                                       }
+                               }
+                       }
+
+                       if (missing != null || BaseType == null)
+                               return missing;
+
+                       return BaseType.ResolveMissingDependencies ();
+               }
+
+               public void SetMetaInfo (MetaType info)
                {
                        if (this.info != null)
                                throw new InternalErrorException ("MetaInfo reset");
@@ -434,69 +768,72 @@ namespace Mono.CSharp
                }
        }
 
-       public sealed class BuildinTypeSpec : TypeSpec
+       //
+       // Special version used for types which must exist in corlib or
+       // the compiler cannot work
+       //
+       public sealed class BuiltinTypeSpec : TypeSpec
        {
                public enum Type
                {
                        None = 0,
 
-                       // TODO: Reorder it more carefully so we can do fast compares
-                       Object,
-                       ValueType,
-                       Attribute,
-                       Int,
-                       UInt,
-                       Long,
-                       ULong,
-                       Float,
-                       Double,
-                       Char,
-                       Short,
-                       Decimal,
-                       Bool,
-                       SByte,
-                       Byte,
-                       UShort,
-                       String,
-                       Enum,
-                       Delegate,
-                       MulticastDelegate,
-                       Void,
-                       Array,
-                       Type,
+                       // Ordered carefully for fast compares
+                       FirstPrimitive = 1,
+                       Bool = 1,
+                       Byte = 2,
+                       SByte = 3,
+                       Char = 4,
+                       Short = 5,
+                       UShort = 6,
+                       Int = 7,
+                       UInt = 8,
+                       Long = 9,
+                       ULong = 10,
+                       Float = 11,
+                       Double = 12,
+                       LastPrimitive = 12,
+                       Decimal = 13,
+
+                       IntPtr = 14,
+                       UIntPtr = 15,
+
+                       Object = 16,
+                       Dynamic = 17,
+                       String = 18,
+                       Type = 19,
+
+                       ValueType = 20,
+                       Enum = 21,
+                       Delegate = 22,
+                       MulticastDelegate = 23,
+                       Array = 24,
+
                        IEnumerator,
                        IEnumerable,
                        IDisposable,
-                       IntPtr,
-                       UIntPtr,
-                       RuntimeFieldHandle,
-                       RuntimeTypeHandle,
                        Exception,
-
-                       Null,
-                       Dynamic
+                       Attribute,
+                       Other,
                }
 
                readonly Type type;
                readonly string ns;
                readonly string name;
 
-               public BuildinTypeSpec (MemberKind kind, string ns, string name, Type buildinKind)
+               public BuiltinTypeSpec (MemberKind kind, string ns, string name, Type builtinKind)
                        : base (kind, null, null, null, Modifiers.PUBLIC)
                {
-                       if (kind == MemberKind.Struct)
-                               modifiers |= Modifiers.SEALED;
-
-                       this.type = buildinKind;
+                       this.type = builtinKind;
                        this.ns = ns;
                        this.name = name;
                }
 
-               public BuildinTypeSpec (string name, Type buildinKind)
-                       : this (MemberKind.InternalCompilerType, "", name, buildinKind)
+               public BuiltinTypeSpec (string name, Type builtinKind)
+                       : this (MemberKind.InternalCompilerType, "", name, builtinKind)
                {
-                       // Make all internal types CLS-compliant, non-obsolete
-                       state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
+                       // Make all internal types CLS-compliant, non-obsolete, compact
+                       state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
                }
 
                #region Properties
@@ -507,7 +844,7 @@ namespace Mono.CSharp
                        }
                }
 
-               public override BuildinTypeSpec.Type BuildinType {
+               public override BuiltinTypeSpec.Type BuiltinType {
                        get {
                                return type;
                        }
@@ -533,6 +870,16 @@ namespace Mono.CSharp
 
                #endregion
 
+               public static bool IsPrimitiveType (TypeSpec type)
+               {
+                       return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.LastPrimitive;
+               }
+
+               public static bool IsPrimitiveTypeOrDecimal (TypeSpec type)
+               {
+                       return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.Decimal;
+               }
+
                public override string GetSignatureForError ()
                {
                        switch (Name) {
@@ -560,10 +907,40 @@ namespace Mono.CSharp
                        return FullName;
                }
 
-               public void SetDefinition (ITypeDefinition td, System.Type type)
+               //
+               // Returns the size of type if known, otherwise, 0
+               //
+               public static int GetSize (TypeSpec type)
+               {
+                       switch (type.BuiltinType) {
+                       case Type.Int:
+                       case Type.UInt:
+                       case Type.Float:
+                               return 4;
+                       case Type.Long:
+                       case Type.ULong:
+                       case Type.Double:
+                               return 8;
+                       case Type.Byte:
+                       case Type.SByte:
+                       case Type.Bool:
+                               return 1;
+                       case Type.Short:
+                       case Type.Char:
+                       case Type.UShort:
+                               return 2;
+                       case Type.Decimal:
+                               return 16;
+                       default:
+                               return 0;
+                       }
+               }
+
+               public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod)
                {
                        this.definition = td;
                        this.info = type;
+                       this.modifiers |= (mod & ~Modifiers.AccessibilityMask);
                }
 
                public void SetDefinition (TypeSpec ts)
@@ -572,9 +949,13 @@ namespace Mono.CSharp
                        this.info = ts.GetMetaInfo ();
                        this.BaseType = ts.BaseType;
                        this.Interfaces = ts.Interfaces;
+                       this.modifiers = ts.Modifiers;
                }
        }
 
+       //
+       // Various type comparers used by compiler
+       //
        static class TypeSpecComparer
        {
                //
@@ -656,8 +1037,8 @@ namespace Mono.CSharp
                                        return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
                                }
 
-                               if (a == InternalType.Dynamic || b == InternalType.Dynamic)
-                                       return b == TypeManager.object_type || a == TypeManager.object_type;
+                               if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
+                                       return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
 
                                if (a.MemberDefinition != b.MemberDefinition)
                                        return false;
@@ -675,6 +1056,23 @@ namespace Mono.CSharp
                                return true;
                        }
 
+                       public static bool IsEqual (TypeSpec[] a, TypeSpec[] b)
+                       {
+                               if (a == b)
+                                       return true;
+
+                               if (a.Length != b.Length)
+                                       return false;
+
+                               for (int i = 0; i < a.Length; ++i) {
+                                       if (!IsEqual (a[i], b[i]))
+                                               return false;
+                               }
+
+                               return true;
+                       }
+
+
                        //
                        // Compares unordered arrays
                        //
@@ -714,8 +1112,7 @@ namespace Mono.CSharp
                                        if (!IsEqual (a.Types[i], b.Types[i]))
                                                return false;
 
-                                       const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
-                                       if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
+                                       if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
                                                return false;
                                }
 
@@ -746,17 +1143,18 @@ namespace Mono.CSharp
                                }
 
                                for (int i = 0; i < targs_definition.Length; ++i) {
+                                       if (TypeSpecComparer.IsEqual (t1_targs[i], t2_targs[i]))
+                                               continue;
+
                                        Variance v = targs_definition[i].Variance;
                                        if (v == Variance.None) {
-                                               if (t1_targs[i] == t2_targs[i])
-                                                       continue;
                                                return false;
                                        }
 
                                        if (v == Variance.Covariant) {
-                                               if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1_targs[i]), t2_targs[i]))
+                                               if (!Convert.ImplicitReferenceConversionExists (t1_targs[i], t2_targs[i]))
                                                        return false;
-                                       } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2_targs[i]), t1_targs[i])) {
+                                       } else if (!Convert.ImplicitReferenceConversionExists (t2_targs[i], t1_targs[i])) {
                                                return false;
                                        }
                                }
@@ -776,8 +1174,17 @@ namespace Mono.CSharp
                        //
                        public static bool IsEqual (TypeSpec a, TypeSpec b)
                        {
-                               if (a.MemberDefinition != b.MemberDefinition)
+                               if (a.MemberDefinition != b.MemberDefinition) {
+                                       var base_ifaces = a.Interfaces;
+                                       if (base_ifaces != null) {
+                                               foreach (var base_iface in base_ifaces) {
+                                                       if (base_iface.Arity > 0 && IsEqual (base_iface, b))
+                                                               return true;
+                                               }
+                                       }
+
                                        return false;
+                               }
 
                                var ta = a.TypeArguments;
                                var tb = b.TypeArguments;
@@ -825,7 +1232,7 @@ namespace Mono.CSharp
                                        //    class X<T> : I<T>, I<float>
                                        // 
                                        if (b.IsGenericParameter)
-                                               return a.DeclaringType == b.DeclaringType;
+                                               return a != b && a.DeclaringType == b.DeclaringType;
 
                                        //
                                        // We're now comparing a type parameter with a
@@ -900,18 +1307,10 @@ namespace Mono.CSharp
                {
                        if (a == b) {
                                // This also rejects dynamic == dynamic
-                               return a.Kind != MemberKind.InternalCompilerType || a == InternalType.Dynamic;
+                               return a.Kind != MemberKind.InternalCompilerType || a.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
                        }
 
-                       //
-                       // object and dynamic are considered equivalent there is an identity conversion
-                       // between object and dynamic, and between constructed types that are the same
-                       // when replacing all occurences of dynamic with object.
-                       //
-                       if (a == InternalType.Dynamic || b == InternalType.Dynamic)
-                               return b == TypeManager.object_type || a == TypeManager.object_type;
-
-                       if (a == null)
+                       if (a == null || b == null)
                                return false;
 
                        if (a.IsArray) {
@@ -920,11 +1319,20 @@ namespace Mono.CSharp
                                if (b_a == null)
                                        return false;
 
-                               return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank;
+                               return a_a.Rank == b_a.Rank && IsEqual (a_a.Element, b_a.Element);
                        }
 
-                       if (!a.IsGeneric || b == null || !b.IsGeneric)
+                       if (!a.IsGeneric || !b.IsGeneric) {
+                               //
+                               // object and dynamic are considered equivalent there is an identity conversion
+                               // between object and dynamic, and between constructed types that are the same
+                               // when replacing all occurences of dynamic with object.
+                               //
+                               if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
+                                       return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
+
                                return false;
+                       }
 
                        if (a.MemberDefinition != b.MemberDefinition)
                                return false;
@@ -945,6 +1353,9 @@ namespace Mono.CSharp
        {
                IAssemblyDefinition DeclaringAssembly { get; }
                string Namespace { get; }
+               bool IsPartial { get; }
+               bool IsComImport { get; }
+               bool IsTypeForwarder { get; }
                int TypeParametersCount { get; }
                TypeParameterSpec[] TypeParameters { get; }
 
@@ -959,19 +1370,14 @@ namespace Mono.CSharp
        {
                public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
                public static readonly InternalType Arglist = new InternalType ("__arglist");
-               public static BuildinTypeSpec Dynamic;
                public static readonly InternalType MethodGroup = new InternalType ("method group");
-               public static BuildinTypeSpec Null;
+               public static readonly InternalType NullLiteral = new InternalType ("null");
                public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
+               public static readonly InternalType Namespace = new InternalType ("<namespace>");
+               public static readonly InternalType ErrorType = new InternalType ("<error>");
 
                readonly string name;
 
-               InternalType (string name, MemberCache cache)
-                       : this (name)
-               {
-                       this.cache = cache;
-               }
-
                InternalType (string name)
                        : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
                {
@@ -980,7 +1386,7 @@ namespace Mono.CSharp
                        cache = MemberCache.Empty;
 
                        // Make all internal types CLS-compliant, non-obsolete
-                       state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
+                       state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
                }
 
                #region Properties
@@ -997,12 +1403,30 @@ namespace Mono.CSharp
                        }
                }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
                bool IMemberDefinition.IsImported {
                        get {
                                return false;
                        }
                }
 
+               bool ITypeDefinition.IsPartial {
+                       get {
+                               return false;
+                       }
+               }
+
+               bool ITypeDefinition.IsTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
                public override string Name {
                        get {
                                return name;
@@ -1071,9 +1495,10 @@ namespace Mono.CSharp
                        return null;
                }
 
-               bool IMemberDefinition.IsNotCLSCompliant ()
-               {
-                       return false;
+               bool? IMemberDefinition.CLSAttributeValue {
+                       get {
+                               return null;
+                       }
                }
 
                void IMemberDefinition.SetIsAssigned ()
@@ -1087,20 +1512,20 @@ namespace Mono.CSharp
                #endregion
        }
 
+       //
+       // Common base class for composite types
+       //
        public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
        {
-               protected ElementTypeSpec (MemberKind kind, TypeSpec element, Type info)
+               protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info)
                        : base (kind, element.DeclaringType, null, info, element.Modifiers)
                {
                        this.Element = element;
 
-                       // Some flags can be copied directly from the element
-                       const StateFlags shared_flags = StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected
-                               | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | StateFlags.HasDynamicElement;
-                       state &= ~shared_flags;
-                       state |= (element.state & shared_flags);
+                       state &= ~SharedStateFlags;
+                       state |= (element.state & SharedStateFlags);
 
-                       if (element == InternalType.Dynamic)
+                       if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
                                state |= StateFlags.HasDynamicElement;
 
                        // Has to use its own type definition instead of just element definition to
@@ -1114,6 +1539,24 @@ namespace Mono.CSharp
 
                public TypeSpec Element { get; private set; }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
+               bool ITypeDefinition.IsPartial {
+                       get {
+                               return false;
+                       }
+               }
+
+               bool ITypeDefinition.IsTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
                public override string Name {
                        get {
                                throw new NotSupportedException ();
@@ -1132,6 +1575,11 @@ namespace Mono.CSharp
                        return null;
                }
 
+               public override string GetSignatureForDocumentation ()
+               {
+                       return Element.GetSignatureForDocumentation () + GetPostfixSignature ();
+               }
+
                public override string GetSignatureForError ()
                {
                        return Element.GetSignatureForError () + GetPostfixSignature ();
@@ -1204,9 +1652,10 @@ namespace Mono.CSharp
                        return Element.MemberDefinition.ConditionalConditions ();
                }
 
-               bool IMemberDefinition.IsNotCLSCompliant ()
-               {
-                       return Element.MemberDefinition.IsNotCLSCompliant ();
+               bool? IMemberDefinition.CLSAttributeValue {
+                       get {
+                               return Element.MemberDefinition.CLSAttributeValue;
+                       }
                }
 
                public void SetIsAssigned ()
@@ -1224,7 +1673,7 @@ namespace Mono.CSharp
 
        public class ArrayContainer : ElementTypeSpec
        {
-               struct TypeRankPair : IEquatable<TypeRankPair>
+               public struct TypeRankPair : IEquatable<TypeRankPair>
                {
                        TypeSpec ts;
                        int rank;
@@ -1251,11 +1700,12 @@ namespace Mono.CSharp
                }
 
                readonly int rank;
-               static Dictionary<TypeRankPair, ArrayContainer> instances = new Dictionary<TypeRankPair, ArrayContainer> ();
+               readonly ModuleContainer module;
 
-               private ArrayContainer (TypeSpec element, int rank)
+               private ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
                        : base (MemberKind.ArrayType, element, null)
                {
+                       this.module = module;
                        this.rank = rank;
                }
 
@@ -1267,11 +1717,11 @@ namespace Mono.CSharp
 
                public MethodInfo GetConstructor ()
                {
-                       var mb = RootContext.ToplevelTypes.Builder;
+                       var mb = module.Builder;
 
-                       var arg_types = new Type[rank];
+                       var arg_types = new MetaType[rank];
                        for (int i = 0; i < rank; i++)
-                               arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
+                               arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
 
                        var ctor = mb.GetArrayMethod (
                                GetMetaInfo (), Constructor.ConstructorName,
@@ -1283,27 +1733,27 @@ namespace Mono.CSharp
 
                public MethodInfo GetAddressMethod ()
                {
-                       var mb = RootContext.ToplevelTypes.Builder;
+                       var mb = module.Builder;
 
-                       var arg_types = new Type[rank];
+                       var arg_types = new MetaType[rank];
                        for (int i = 0; i < rank; i++)
-                               arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
+                               arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
 
                        var address = mb.GetArrayMethod (
                                GetMetaInfo (), "Address",
                                CallingConventions.HasThis | CallingConventions.Standard,
-                               ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
+                               ReferenceContainer.MakeType (module, Element).GetMetaInfo (), arg_types);
 
                        return address;
                }
 
                public MethodInfo GetGetMethod ()
                {
-                       var mb = RootContext.ToplevelTypes.Builder;
+                       var mb = module.Builder;
 
-                       var arg_types = new Type[rank];
+                       var arg_types = new MetaType[rank];
                        for (int i = 0; i < rank; i++)
-                               arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
+                               arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
 
                        var get = mb.GetArrayMethod (
                                GetMetaInfo (), "Get",
@@ -1315,23 +1765,23 @@ namespace Mono.CSharp
 
                public MethodInfo GetSetMethod ()
                {
-                       var mb = RootContext.ToplevelTypes.Builder;
+                       var mb = module.Builder;
 
-                       var arg_types = new Type[rank + 1];
+                       var arg_types = new MetaType[rank + 1];
                        for (int i = 0; i < rank; i++)
-                               arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
+                               arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
 
                        arg_types[rank] = Element.GetMetaInfo ();
 
                        var set = mb.GetArrayMethod (
                                GetMetaInfo (), "Set",
                                CallingConventions.HasThis | CallingConventions.Standard,
-                               TypeManager.void_type.GetMetaInfo (), arg_types);
+                               module.Compiler.BuiltinTypes.Void.GetMetaInfo (), arg_types);
 
                        return set;
                }
 
-               public override Type GetMetaInfo ()
+               public override MetaType GetMetaInfo ()
                {
                        if (info == null) {
                                if (rank == 1)
@@ -1360,42 +1810,60 @@ namespace Mono.CSharp
                        return sb.ToString ();
                }
 
-               public static ArrayContainer MakeType (TypeSpec element)
+               public override string GetSignatureForDocumentation ()
                {
-                       return MakeType (element, 1);
+                       StringBuilder sb = new StringBuilder ();
+                       GetElementSignatureForDocumentation (sb);
+                       return sb.ToString ();
                }
 
-               public static ArrayContainer MakeType (TypeSpec element, int rank)
+               void GetElementSignatureForDocumentation (StringBuilder sb)
+               {
+                       var ac = Element as ArrayContainer;
+                       if (ac == null)
+                               sb.Append (Element.GetSignatureForDocumentation ());
+                       else
+                               ac.GetElementSignatureForDocumentation (sb);
+
+                       sb.Append ("[");
+                       for (int i = 1; i < rank; i++) {
+                               if (i == 1)
+                                       sb.Append ("0:");
+
+                               sb.Append (",0:");
+                       }
+                       sb.Append ("]");
+               }
+
+               public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element)
+               {
+                       return MakeType (module, element, 1);
+               }
+
+               public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element, int rank)
                {
                        ArrayContainer ac;
                        var key = new TypeRankPair (element, rank);
-                       if (!instances.TryGetValue (key, out ac)) {
-                               ac = new ArrayContainer (element, rank) {
-                                       BaseType = TypeManager.array_type
+                       if (!module.ArrayTypesCache.TryGetValue (key, out ac)) {
+                               ac = new ArrayContainer (module, element, rank) {
+                                       BaseType = module.Compiler.BuiltinTypes.Array
                                };
 
-                               instances.Add (key, ac);
+                               module.ArrayTypesCache.Add (key, ac);
                        }
 
                        return ac;
                }
-
-               public static void Reset ()
-               {
-                       instances = new Dictionary<TypeRankPair, ArrayContainer> ();
-               }
        }
 
        class ReferenceContainer : ElementTypeSpec
        {
-               static Dictionary<TypeSpec, ReferenceContainer> instances = new Dictionary<TypeSpec, ReferenceContainer> ();
-
                private ReferenceContainer (TypeSpec element)
                        : base (MemberKind.Class, element, null)        // TODO: Kind.Class is most likely wrong
                {
                }
 
-               public override Type GetMetaInfo ()
+               public override MetaType GetMetaInfo ()
                {
                        if (info == null) {
                                info = Element.GetMetaInfo ().MakeByRefType ();
@@ -1404,27 +1872,20 @@ namespace Mono.CSharp
                        return info;
                }
 
-               public static ReferenceContainer MakeType (TypeSpec element)
+               public static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element)
                {
                        ReferenceContainer pc;
-                       if (!instances.TryGetValue (element, out pc)) {
+                       if (!module.ReferenceTypesCache.TryGetValue (element, out pc)) {
                                pc = new ReferenceContainer (element);
-                               instances.Add (element, pc);
+                               module.ReferenceTypesCache.Add (element, pc);
                        }
 
                        return pc;
                }
-
-               public static void Reset ()
-               {
-                       instances = new Dictionary<TypeSpec, ReferenceContainer> ();
-               }
        }
 
        class PointerContainer : ElementTypeSpec
        {
-               static Dictionary<TypeSpec, PointerContainer> instances = new Dictionary<TypeSpec, PointerContainer> ();
-
                private PointerContainer (TypeSpec element)
                        : base (MemberKind.PointerType, element, null)
                {
@@ -1432,7 +1893,7 @@ namespace Mono.CSharp
                        state &= ~StateFlags.CLSCompliant_Undetected;
                }
 
-               public override Type GetMetaInfo ()
+               public override MetaType GetMetaInfo ()
                {
                        if (info == null) {
                                info = Element.GetMetaInfo ().MakePointerType ();
@@ -1446,20 +1907,15 @@ namespace Mono.CSharp
                        return "*";
                }
 
-               public static PointerContainer MakeType (TypeSpec element)
+               public static PointerContainer MakeType (ModuleContainer module, TypeSpec element)
                {
                        PointerContainer pc;
-                       if (!instances.TryGetValue (element, out pc)) {
+                       if (!module.PointerTypesCache.TryGetValue (element, out pc)) {
                                pc = new PointerContainer (element);
-                               instances.Add (element, pc);
+                               module.PointerTypesCache.Add (element, pc);
                        }
 
                        return pc;
                }
-
-               public static void Reset ()
-               {
-                       instances = new Dictionary<TypeSpec, PointerContainer> ();
-               }
        }
 }