Clenup few checks.
[mono.git] / mcs / mcs / typespec.cs
index 2a4b8a06bad466ffe48cbad1d1739a31263082b3..22278a08dacd4806887da44e02ad0cfb9f93184e 100644 (file)
@@ -76,7 +76,9 @@ namespace Mono.CSharp
                }
 
                public bool IsArray {
-                       get { return this is ArrayContainer; }
+                       get {
+                               return Kind == MemberKind.ArrayType;
+                       }
                }
 
                public bool IsAttribute {
@@ -113,7 +115,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;
@@ -238,8 +240,17 @@ 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 ()
@@ -606,12 +617,23 @@ 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) {
+                                       //
+                                       // Internal compiler variance between G<object> and G<dynamic>
+                                       //
+                                       for (int i = 0; i < targs_definition.Length; ++i) {
+                                               if ((t1_targs[i] != TypeManager.object_type && t1_targs[i] != InternalType.Dynamic) ||
+                                                       (t2_targs[i] != TypeManager.object_type && t2_targs[i] != InternalType.Dynamic))
+                                                       return false;
+                                       }
+
+                                       return true;
+                               }
+
                                for (int i = 0; i < targs_definition.Length; ++i) {
                                        Variance v = targs_definition[i].Variance;
                                        if (v == Variance.None) {
@@ -656,6 +678,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 +729,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)
@@ -781,18 +811,35 @@ namespace Mono.CSharp
                        state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
                }
 
+               public override int Arity {
+                       get {
+                               return 0;
+                       }
+               }
+
+               public override string Name {
+                       get {
+                               return name;
+                       }
+               }
+
                public override string GetSignatureForError ()
                {
                        return name;
                }
        }
 
-       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)
+                       : base (kind, element.DeclaringType, null, info, element.Modifiers)
                {
                        this.Element = element;
+
+                       // 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 +881,108 @@ namespace Mono.CSharp
                        mutated.info = null;
                        return mutated;
                }
+
+               #region ITypeDefinition Members
+
+               System.Reflection.Assembly IMemberDefinition.Assembly {
+                       get {
+                               return Element.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 MemberCache LoadMembers (TypeSpec declaringType)
+               {
+                       return Element.MemberDefinition.LoadMembers (declaringType);
+               }
+
+               public bool IsImported {
+                       get {
+                               return Element.MemberDefinition.IsImported;
+                       }
+               }
+
+               public string[] ConditionalConditions ()
+               {
+                       return Element.MemberDefinition.ConditionalConditions ();
+               }
+
+               bool IMemberDefinition.IsNotCLSCompliant ()
+               {
+                       return Element.MemberDefinition.IsNotCLSCompliant ();
+               }
+
+               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;
                }
@@ -869,6 +1009,22 @@ namespace Mono.CSharp
                        return ctor;
                }
 
+               public System.Reflection.MethodInfo GetAddressMethod ()
+               {
+                       var mb = RootContext.ToplevelTypes.Builder;
+
+                       var arg_types = new Type[rank];
+                       for (int i = 0; i < rank; i++)
+                               arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
+
+                       var address = mb.GetArrayMethod (
+                               GetMetaInfo (), "Address",
+                               System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
+                               ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
+
+                       return address;
+               }
+
                public System.Reflection.MethodInfo GetGetMethod ()
                {
                        var mb = RootContext.ToplevelTypes.Builder;
@@ -916,6 +1072,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 +1096,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 +1110,7 @@ namespace Mono.CSharp
 
                public static void Reset ()
                {
-                       instances = new Dictionary<Tuple<TypeSpec, int>, ArrayContainer> ();
+                       instances = new Dictionary<TypeRankPair, ArrayContainer> ();
                }
        }