Enable eval statements
[mono.git] / mcs / mcs / typespec.cs
index 2a4b8a06bad466ffe48cbad1d1739a31263082b3..488ad0d533022d151867942012d1a54218afe15f 100644 (file)
 using System;
 using System.Collections.Generic;
 using System.Text;
-using System.Linq;
+
+#if STATIC
+using MetaType = IKVM.Reflection.Type;
+using IKVM.Reflection;
+#else
+using MetaType = System.Type;
+using System.Reflection;
+#endif
 
 namespace Mono.CSharp
 {
        public class TypeSpec : MemberSpec
        {
-               protected Type info;
+               protected MetaType info;
                protected MemberCache cache;
                protected IList<TypeSpec> ifaces;
                TypeSpec base_type;
@@ -26,9 +33,10 @@ namespace Mono.CSharp
 
                public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
 
+#if !STATIC
                // Reflection Emit hacking
-               static Type TypeBuilder;
-               static Type GenericTypeBuilder;
+               static readonly Type TypeBuilder;
+               static readonly Type GenericTypeBuilder;
 
                static TypeSpec ()
                {
@@ -38,8 +46,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,6 +75,18 @@ namespace Mono.CSharp
                        }
                }
 
+               public virtual BuildinTypeSpec.Type BuildinType {
+                       get {
+                               return BuildinTypeSpec.Type.None;
+                       }
+               }
+
+               public bool HasDynamicElement {
+                       get {
+                               return (state & StateFlags.HasDynamicElement) != 0;
+                       }
+               }
+
                public virtual IList<TypeSpec> Interfaces {
                        get {
                                return ifaces;
@@ -76,7 +97,9 @@ namespace Mono.CSharp
                }
 
                public bool IsArray {
-                       get { return this is ArrayContainer; }
+                       get {
+                               return Kind == MemberKind.ArrayType;
+                       }
                }
 
                public bool IsAttribute {
@@ -113,7 +136,7 @@ namespace Mono.CSharp
 
                public bool IsConstantCompatible {
                        get {
-                               if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate)) != 0)
+                               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;
@@ -172,8 +195,12 @@ namespace Mono.CSharp
 
                public bool IsTypeBuilder {
                        get {
+#if STATIC
+                               return true;
+#else
                                var meta = GetMetaInfo().GetType ();
                                return meta == TypeBuilder || meta == GenericTypeBuilder;
+#endif
                        }
                }
 
@@ -192,9 +219,12 @@ namespace Mono.CSharp
                        }
                }
 
-               public virtual MemberCache MemberCacheTypes {
+               public MemberCache MemberCacheTypes {
                        get {
-                               return MemberCache;
+                               if (cache == null)
+                                       InitializeMemberCache (true);
+
+                               return cache;
                        }
                }       
 
@@ -238,11 +268,20 @@ namespace Mono.CSharp
                        if (!pa.IsDefined)
                                return Attribute.DefaultUsageAttribute;
 
-                       var aua = MemberDefinition.GetAttributeUsage (pa);
-                       return aua ?? Attribute.DefaultUsageAttribute;
+                       AttributeUsageAttribute aua = null;
+                       var type = this;
+                       while (type != null) {
+                               aua = type.MemberDefinition.GetAttributeUsage (pa);
+                               if (aua != null)
+                                       break;
+
+                               type = type.BaseType;
+                       }
+
+                       return aua;
                }
 
-               public virtual Type GetMetaInfo ()
+               public virtual MetaType GetMetaInfo ()
                {
                        return info;
                }
@@ -258,6 +297,8 @@ namespace Mono.CSharp
 
                        if (IsNested) {
                                s = DeclaringType.GetSignatureForError ();
+                       } else if (MemberDefinition is AnonymousTypeClass) {
+                               return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
                        } else {
                                s = MemberDefinition.Namespace;
                        }
@@ -276,13 +317,16 @@ namespace Mono.CSharp
                        return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
                }
 
-               public bool ImplementsInterface (TypeSpec iface)
+               public bool ImplementsInterface (TypeSpec iface, bool variantly)
                {
                        var t = this;
                        do {
                                if (t.Interfaces != null) {     // TODO: Try t.iface
                                        foreach (TypeSpec i in t.Interfaces) {
-                                               if (i == iface || TypeSpecComparer.Variant.IsEqual (i, iface))
+                                               if (i == iface || TypeSpecComparer.IsEqual (i, iface))
+                                                       return true;
+
+                                               if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface))
                                                        return true;
                                        }
                                }
@@ -295,14 +339,43 @@ namespace Mono.CSharp
 
                protected virtual void InitializeMemberCache (bool onlyTypes)
                {
-                       //
-                       // Not interested in members of nested private types
-                       //
-                       if (IsPrivate) {
-                               cache = new MemberCache (0);
-                       } else {
-                               cache = MemberDefinition.LoadMembers (this);
+                       MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
+
+                       if (onlyTypes)
+                               state |= StateFlags.PendingMemberCacheMembers;
+                       else
+                               state &= ~StateFlags.PendingMemberCacheMembers;
+               }
+
+               //
+               // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
+               // comparison is used to hide differences between `object' and `dynamic' for generic
+               // types. Should not be used for comparisons where G<object> != G<dynamic>
+               //
+               public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
+               {
+                       if (dynamicIsObject && baseClass.IsGeneric) {
+                               //
+                               // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
+                               //
+                               // class B : A<object> {}
+                               //
+                               while (type != null) {
+                                       type = type.BaseType;
+                                       if (TypeSpecComparer.IsEqual (type, baseClass))
+                                               return true;
+                               }
+
+                               return false;
+                       }
+
+                       while (type != null) {
+                               type = type.BaseType;
+                               if (type == baseClass)
+                                       return true;
                        }
+
+                       return false;
                }
 
                public override MemberSpec InflateMember (TypeParameterInflator inflator)
@@ -313,8 +386,9 @@ namespace Mono.CSharp
                        // When inflating nested type from inside the type instance will be same
                        // because type parameters are same for all nested types
                        //
-                       if (DeclaringType == inflator.TypeInstance)
+                       if (DeclaringType == inflator.TypeInstance) {
                                return MakeGenericType (targs);
+                       }
 
                        return new InflatedTypeSpec (this, inflator.TypeInstance, targs);
                }
@@ -322,16 +396,30 @@ namespace Mono.CSharp
                public InflatedTypeSpec MakeGenericType (TypeSpec[] targs)
                {
                        if (targs.Length == 0 && !IsNested)
-                               throw new ArgumentException ("Empty type arguments");
+                               throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
 
                        InflatedTypeSpec instance;
 
-                       if (inflated_instances == null)
+                       if (inflated_instances == null) {
                                inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
 
+                               if (IsNested) {
+                                       instance = this as InflatedTypeSpec;
+                                       if (instance != null) {
+                                               //
+                                               // Nested types could be inflated on already inflated instances
+                                               // Caching this type ensured we are using same instance for
+                                               // inside/outside inflation using local type parameters
+                                               //
+                                               inflated_instances.Add (TypeArguments, instance);
+                                       }
+                               }
+                       }
+
                        if (!inflated_instances.TryGetValue (targs, out instance)) {
                                if (GetDefinition () != this && !IsNested)
-                                       throw new InternalErrorException ("Only type definition or nested non-inflated types can be used to call MakeGenericType");
+                                       throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
+                                               GetSignatureForError ());
 
                                instance = new InflatedTypeSpec (this, declaringType, targs);
                                inflated_instances.Add (targs, instance);
@@ -345,7 +433,43 @@ 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 (missing != null || BaseType == null)
+                               return missing;
+
+                       return BaseType.ResolveMissingDependencies ();
+               }
+
+               public void SetMetaInfo (MetaType info)
                {
                        if (this.info != null)
                                throw new InternalErrorException ("MetaInfo reset");
@@ -359,24 +483,88 @@ namespace Mono.CSharp
                }
        }
 
-       public class PredefinedTypeSpec : TypeSpec
+       public sealed class BuildinTypeSpec : TypeSpec
        {
-               string name;
-               string ns;
+               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,
+                       IEnumerator,
+                       IEnumerable,
+                       IDisposable,
+                       IntPtr,
+                       UIntPtr,
+                       RuntimeFieldHandle,
+                       RuntimeTypeHandle,
+                       Exception,
+
+                       Null,
+                       Dynamic
+               }
+
+               readonly Type type;
+               readonly string ns;
+               readonly string name;
 
-               public PredefinedTypeSpec (MemberKind kind, string ns, string name)
+               public BuildinTypeSpec (MemberKind kind, string ns, string name, Type buildinKind)
                        : base (kind, null, null, null, Modifiers.PUBLIC)
                {
-                       this.name = name;
+                       this.type = buildinKind;
                        this.ns = ns;
+                       this.name = name;
                }
 
+               public BuildinTypeSpec (string name, Type buildinKind)
+                       : this (MemberKind.InternalCompilerType, "", name, buildinKind)
+               {
+                       // Make all internal types CLS-compliant, non-obsolete, compact
+                       state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
+               }
+
+               #region Properties
+
                public override int Arity {
                        get {
                                return 0;
                        }
                }
 
+               public override BuildinTypeSpec.Type BuildinType {
+                       get {
+                               return type;
+                       }
+               }
+
+               public string FullName {
+                       get {
+                               return ns + '.' + name;
+                       }
+               }
+
                public override string Name {
                        get {
                                return name;
@@ -389,9 +577,11 @@ namespace Mono.CSharp
                        }
                }
 
+               #endregion
+
                public override string GetSignatureForError ()
                {
-                       switch (name) {
+                       switch (Name) {
                        case "Int32": return "int";
                        case "Int64": return "long";
                        case "String": return "string";
@@ -410,13 +600,17 @@ namespace Mono.CSharp
                        case "SByte": return "sbyte";
                        }
 
-                       return ns + "." + name;
+                       if (ns.Length == 0)
+                               return name;
+
+                       return FullName;
                }
 
-               public void SetDefinition (ITypeDefinition td, Type type)
+               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)
@@ -425,28 +619,29 @@ namespace Mono.CSharp
                        this.info = ts.GetMetaInfo ();
                        this.BaseType = ts.BaseType;
                        this.Interfaces = ts.Interfaces;
+                       this.modifiers = ts.Modifiers;
                }
        }
 
        static class TypeSpecComparer
        {
                //
-               // Default reference comparison
+               // Does strict reference comparion only
                //
                public static readonly DefaultImpl Default = new DefaultImpl ();
 
-               public class DefaultImpl : IEqualityComparer<TypeSpec[]>, IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>
+               public class DefaultImpl : IEqualityComparer<TypeSpec[]>
                {
                        #region IEqualityComparer<TypeSpec[]> Members
 
-                       public bool Equals (TypeSpec[] x, TypeSpec[] y)
+                       bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
                        {
-                               if (x.Length != y.Length)
-                                       return false;
-
                                if (x == y)
                                        return true;
 
+                               if (x.Length != y.Length)
+                                       return false;
+
                                for (int i = 0; i < x.Length; ++i)
                                        if (x[i] != y[i])
                                                return false;
@@ -454,7 +649,7 @@ namespace Mono.CSharp
                                return true;
                        }
 
-                       public int GetHashCode (TypeSpec[] obj)
+                       int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
                        {
                                int hash = 0;
                                for (int i = 0; i < obj.Length; ++i)
@@ -464,20 +659,6 @@ namespace Mono.CSharp
                        }
 
                        #endregion
-
-                       #region IEqualityComparer<Tuple<TypeSpec,TypeSpec[]>> Members
-
-                       bool IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>.Equals (Tuple<TypeSpec, TypeSpec[]> x, Tuple<TypeSpec, TypeSpec[]> y)
-                       {
-                               return Equals (x.Item2, y.Item2) && x.Item1 == y.Item1;
-                       }
-
-                       int IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>.GetHashCode (Tuple<TypeSpec, TypeSpec[]> obj)
-                       {
-                               return GetHashCode (obj.Item2) ^ obj.Item1.GetHashCode ();
-                       }
-
-                       #endregion
                }
 
                //
@@ -517,21 +698,6 @@ namespace Mono.CSharp
                                        return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
                                }
 
-                               if (a.TypeArguments.Length != b.TypeArguments.Length)
-                                       return false;
-
-                               if (a.TypeArguments.Length != 0) {
-                                       if (a.MemberDefinition != b.MemberDefinition)
-                                               return false;
-
-                                       for (int i = 0; i < a.TypeArguments.Length; ++i) {
-                                               if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
-                                                       return false;
-                                       }
-
-                                       return true;
-                               }
-
                                var ac_a = a as ArrayContainer;
                                if (ac_a != null) {
                                        var ac_b = b as ArrayContainer;
@@ -541,7 +707,20 @@ namespace Mono.CSharp
                                if (a == InternalType.Dynamic || b == InternalType.Dynamic)
                                        return b == TypeManager.object_type || a == TypeManager.object_type;
 
-                               return false;
+                               if (a.MemberDefinition != b.MemberDefinition)
+                                       return false;
+
+                               do {
+                                       for (int i = 0; i < a.TypeArguments.Length; ++i) {
+                                               if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
+                                                       return false;
+                                       }
+
+                                       a = a.DeclaringType;
+                                       b = b.DeclaringType;
+                               } while (a != null);
+
+                               return true;
                        }
 
                        //
@@ -606,12 +785,14 @@ namespace Mono.CSharp
                                if (type1.MemberDefinition != target_type_def)
                                        return false;
 
-                               if (!type1.IsInterface && !type1.IsDelegate)
-                                       return false;
-
                                var t1_targs = type1.TypeArguments;
                                var t2_targs = type2.TypeArguments;
                                var targs_definition = target_type_def.TypeParameters;
+
+                               if (!type1.IsInterface && !type1.IsDelegate) {
+                                       return false;
+                               }
+
                                for (int i = 0; i < targs_definition.Length; ++i) {
                                        Variance v = targs_definition[i].Variance;
                                        if (v == Variance.None) {
@@ -656,6 +837,20 @@ namespace Mono.CSharp
                                return true;
                        }
 
+                       static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
+                       {
+                               TypeSpec[] targs = type.TypeArguments;
+                               for (int i = 0; i < targs.Length; i++) {
+                                       if (tparam == targs[i])
+                                               return true;
+
+                                       if (ContainsTypeParameter (tparam, targs[i]))
+                                               return true;
+                               }
+
+                               return false;
+                       }
+
                        /// <summary>
                        ///   Check whether `a' and `b' may become equal generic types.
                        ///   The algorithm to do that is a little bit complicated.
@@ -693,13 +888,7 @@ namespace Mono.CSharp
                                        //    class X<T> : I<T>, I<X<T>> -> ok
                                        //
 
-                                       TypeSpec[] bargs = b.TypeArguments;
-                                       for (int i = 0; i < bargs.Length; i++) {
-                                               if (a.Equals (bargs[i]))
-                                                       return false;
-                                       }
-
-                                       return true;
+                                       return !ContainsTypeParameter (a, b);
                                }
 
                                if (b.IsGenericParameter)
@@ -733,10 +922,76 @@ namespace Mono.CSharp
                                return false;
                        }
                }
+
+               public static bool Equals (TypeSpec[] x, TypeSpec[] y)
+               {
+                       if (x == y)
+                               return true;
+
+                       if (x.Length != y.Length)
+                               return false;
+
+                       for (int i = 0; i < x.Length; ++i)
+                               if (!IsEqual (x[i], y[i]))
+                                       return false;
+
+                       return true;
+               }
+
+               //
+               // Identity type conversion
+               //
+               // Default reference comparison, it has to be used when comparing
+               // two possible dynamic/internal types
+               //
+               public static bool IsEqual (TypeSpec a, TypeSpec b)
+               {
+                       if (a == b) {
+                               // This also rejects dynamic == dynamic
+                               return a.Kind != MemberKind.InternalCompilerType || a == InternalType.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)
+                               return false;
+
+                       if (a.IsArray) {
+                               var a_a = (ArrayContainer) a;
+                               var b_a = b as ArrayContainer;
+                               if (b_a == null)
+                                       return false;
+
+                               return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank;
+                       }
+
+                       if (!a.IsGeneric || b == null || !b.IsGeneric)
+                               return false;
+
+                       if (a.MemberDefinition != b.MemberDefinition)
+                               return false;
+
+                       do {
+                               if (!Equals (a.TypeArguments, b.TypeArguments))
+                                       return false;
+
+                               a = a.DeclaringType;
+                               b = b.DeclaringType;
+                       } while (a != null);
+
+                       return true;
+               }
        }
 
        public interface ITypeDefinition : IMemberDefinition
        {
+               IAssemblyDefinition DeclaringAssembly { get; }
                string Namespace { get; }
                int TypeParametersCount { get; }
                TypeParameterSpec[] TypeParameters { get; }
@@ -744,55 +999,163 @@ namespace Mono.CSharp
                TypeSpec GetAttributeCoClass ();
                string GetAttributeDefaultMember ();
                AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
-               MemberCache LoadMembers (TypeSpec declaringType);
+               bool IsInternalAsPublic (IAssemblyDefinition assembly);
+               void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
        }
 
-       class InternalType : TypeSpec
+       class InternalType : TypeSpec, ITypeDefinition
        {
-               private class DynamicType : InternalType
-               {
-                       public DynamicType ()
-                               : base ("dynamic")
-                       {
-                       }
-
-                       public override Type GetMetaInfo ()
-                       {
-                               return typeof (object);
-                       }
-               }
-
-               public static readonly TypeSpec AnonymousMethod = new InternalType ("anonymous method");
-               public static readonly TypeSpec Arglist = new InternalType ("__arglist");
-               public static readonly TypeSpec Dynamic = new DynamicType ();
-               public static readonly TypeSpec MethodGroup = new InternalType ("method group");
-               public static readonly TypeSpec Null = new InternalType ("null");
-               public static readonly TypeSpec FakeInternalType = new InternalType ("<fake$type>");
+               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 FakeInternalType = new InternalType ("<fake$type>");
 
                readonly string name;
 
-               protected InternalType (string name)
+               InternalType (string name, MemberCache cache)
+                       : this (name)
+               {
+                       this.cache = cache;
+               }
+
+               InternalType (string name)
                        : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
                {
                        this.name = name;
+                       this.definition = this;
                        cache = MemberCache.Empty;
 
                        // Make all internal types CLS-compliant, non-obsolete
                        state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
                }
 
+               #region Properties
+
+               public override int Arity {
+                       get {
+                               return 0;
+                       }
+               }
+
+               IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               bool IMemberDefinition.IsImported {
+                       get {
+                               return false;
+                       }
+               }
+
+               public override string Name {
+                       get {
+                               return name;
+                       }
+               }
+
+               string ITypeDefinition.Namespace {
+                       get {
+                               return null;
+                       }
+               }
+
+               int ITypeDefinition.TypeParametersCount {
+                       get {
+                               return 0;
+                       }
+               }
+
+               TypeParameterSpec[] ITypeDefinition.TypeParameters {
+                       get {
+                               return null;
+                       }
+               }
+
+               #endregion
+
                public override string GetSignatureForError ()
                {
                        return name;
                }
+
+               #region ITypeDefinition Members
+
+               TypeSpec ITypeDefinition.GetAttributeCoClass ()
+               {
+                       return null;
+               }
+
+               string ITypeDefinition.GetAttributeDefaultMember ()
+               {
+                       return null;
+               }
+
+               AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
+               {
+                       return null;
+               }
+
+               bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               string[] IMemberDefinition.ConditionalConditions ()
+               {
+                       return null;
+               }
+
+               ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
+               {
+                       return null;
+               }
+
+               bool? IMemberDefinition.CLSAttributeValue {
+                       get {
+                               return null;
+                       }
+               }
+
+               void IMemberDefinition.SetIsAssigned ()
+               {
+               }
+
+               void IMemberDefinition.SetIsUsed ()
+               {
+               }
+
+               #endregion
        }
 
-       public abstract class ElementTypeSpec : TypeSpec
+       public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
        {
-               protected ElementTypeSpec (MemberKind kind, TypeSpec element, Type info)
-                       : base (kind, element.DeclaringType, element.MemberDefinition, info, element.Modifiers)
+               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);
+
+                       if (element == InternalType.Dynamic)
+                               state |= StateFlags.HasDynamicElement;
+
+                       // Has to use its own type definition instead of just element definition to
+                       // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
+                       this.definition = this;
+
                        cache = MemberCache.Empty;
                }
 
@@ -834,15 +1197,114 @@ namespace Mono.CSharp
                        mutated.info = null;
                        return mutated;
                }
+
+               #region ITypeDefinition Members
+
+               IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
+                       get {
+                               return Element.MemberDefinition.DeclaringAssembly;
+                       }
+               }
+
+               bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
+               {
+                       return Element.MemberDefinition.IsInternalAsPublic (assembly);
+               }
+
+               public string Namespace {
+                       get { throw new NotImplementedException (); }
+               }
+
+               public int TypeParametersCount {
+                       get {
+                               return 0;
+                       }
+               }
+
+               public TypeParameterSpec[] TypeParameters {
+                       get {
+                               throw new NotSupportedException ();
+                       }
+               }
+
+               public TypeSpec GetAttributeCoClass ()
+               {
+                       return Element.MemberDefinition.GetAttributeCoClass ();
+               }
+
+               public string GetAttributeDefaultMember ()
+               {
+                       return Element.MemberDefinition.GetAttributeDefaultMember ();
+               }
+
+               public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
+               {
+                       Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
+               }
+
+               public bool IsImported {
+                       get {
+                               return Element.MemberDefinition.IsImported;
+                       }
+               }
+
+               public string[] ConditionalConditions ()
+               {
+                       return Element.MemberDefinition.ConditionalConditions ();
+               }
+
+               bool? IMemberDefinition.CLSAttributeValue {
+                       get {
+                               return Element.MemberDefinition.CLSAttributeValue;
+                       }
+               }
+
+               public void SetIsAssigned ()
+               {
+                       Element.MemberDefinition.SetIsAssigned ();
+               }
+
+               public void SetIsUsed ()
+               {
+                       Element.MemberDefinition.SetIsUsed ();
+               }
+
+               #endregion
        }
 
        public class ArrayContainer : ElementTypeSpec
        {
+               struct TypeRankPair : IEquatable<TypeRankPair>
+               {
+                       TypeSpec ts;
+                       int rank;
+
+                       public TypeRankPair (TypeSpec ts, int rank)
+                       {
+                               this.ts = ts;
+                               this.rank = rank;
+                       }
+
+                       public override int GetHashCode ()
+                       {
+                               return ts.GetHashCode () ^ rank.GetHashCode ();
+                       }
+
+                       #region IEquatable<Tuple<T1,T2>> Members
+
+                       public bool Equals (TypeRankPair other)
+                       {
+                               return other.ts == ts && other.rank == rank;
+                       }
+
+                       #endregion
+               }
+
                readonly int rank;
-               static Dictionary<Tuple<TypeSpec, int>, ArrayContainer> instances = new Dictionary<Tuple<TypeSpec, int>, ArrayContainer> ();
+               static Dictionary<TypeRankPair, ArrayContainer> instances = new Dictionary<TypeRankPair, ArrayContainer> ();
 
                private ArrayContainer (TypeSpec element, int rank)
-                       : base (MemberKind.Class, element, null)
+                       : base (MemberKind.ArrayType, element, null)
                {
                        this.rank = rank;
                }
@@ -853,43 +1315,59 @@ namespace Mono.CSharp
                        }
                }
 
-               public System.Reflection.MethodInfo GetConstructor ()
+               public MethodInfo GetConstructor ()
                {
                        var mb = RootContext.ToplevelTypes.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 ();
 
                        var ctor = mb.GetArrayMethod (
-                               GetMetaInfo (), ".ctor",
-                               System.Reflection.CallingConventions.HasThis,
+                               GetMetaInfo (), Constructor.ConstructorName,
+                               CallingConventions.HasThis,
                                null, arg_types);
 
                        return ctor;
                }
 
-               public System.Reflection.MethodInfo GetGetMethod ()
+               public MethodInfo GetAddressMethod ()
                {
                        var mb = RootContext.ToplevelTypes.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 ();
+
+                       var address = mb.GetArrayMethod (
+                               GetMetaInfo (), "Address",
+                               CallingConventions.HasThis | CallingConventions.Standard,
+                               ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
+
+                       return address;
+               }
+
+               public MethodInfo GetGetMethod ()
+               {
+                       var mb = RootContext.ToplevelTypes.Builder;
+
+                       var arg_types = new MetaType[rank];
                        for (int i = 0; i < rank; i++)
                                arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
 
                        var get = mb.GetArrayMethod (
                                GetMetaInfo (), "Get",
-                               System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
+                               CallingConventions.HasThis | CallingConventions.Standard,
                                Element.GetMetaInfo (), arg_types);
 
                        return get;
                }
 
-               public System.Reflection.MethodInfo GetSetMethod ()
+               public MethodInfo GetSetMethod ()
                {
                        var mb = RootContext.ToplevelTypes.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 ();
 
@@ -897,13 +1375,13 @@ namespace Mono.CSharp
 
                        var set = mb.GetArrayMethod (
                                GetMetaInfo (), "Set",
-                               System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
+                               CallingConventions.HasThis | CallingConventions.Standard,
                                TypeManager.void_type.GetMetaInfo (), arg_types);
 
                        return set;
                }
 
-               public override Type GetMetaInfo ()
+               public override MetaType GetMetaInfo ()
                {
                        if (info == null) {
                                if (rank == 1)
@@ -916,6 +1394,11 @@ namespace Mono.CSharp
                }
 
                protected override string GetPostfixSignature()
+               {
+                       return GetPostfixSignature (rank);
+               }
+
+               public static string GetPostfixSignature (int rank)
                {
                        StringBuilder sb = new StringBuilder ();
                        sb.Append ("[");
@@ -935,7 +1418,7 @@ namespace Mono.CSharp
                public static ArrayContainer MakeType (TypeSpec element, int rank)
                {
                        ArrayContainer ac;
-                       var key = Tuple.Create (element, rank);
+                       var key = new TypeRankPair (element, rank);
                        if (!instances.TryGetValue (key, out ac)) {
                                ac = new ArrayContainer (element, rank) {
                                        BaseType = TypeManager.array_type
@@ -949,7 +1432,7 @@ namespace Mono.CSharp
 
                public static void Reset ()
                {
-                       instances = new Dictionary<Tuple<TypeSpec, int>, ArrayContainer> ();
+                       instances = new Dictionary<TypeRankPair, ArrayContainer> ();
                }
        }
 
@@ -962,7 +1445,7 @@ namespace Mono.CSharp
                {
                }
 
-               public override Type GetMetaInfo ()
+               public override MetaType GetMetaInfo ()
                {
                        if (info == null) {
                                info = Element.GetMetaInfo ().MakeByRefType ();
@@ -999,7 +1482,7 @@ namespace Mono.CSharp
                        state &= ~StateFlags.CLSCompliant_Undetected;
                }
 
-               public override Type GetMetaInfo ()
+               public override MetaType GetMetaInfo ()
                {
                        if (info == null) {
                                info = Element.GetMetaInfo ().MakePointerType ();