Tue Nov 14 16:06:37 CET 2006 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / mcs / typemanager.cs
index 967a23de1558fdf3234f7ec566d39bb04f2d2b58..308faf58212b6d1db024b322a0a3047d32450a89 100644 (file)
@@ -70,6 +70,7 @@ public partial class TypeManager {
        static public Type iasyncresult_type;
        static public Type asynccallback_type;
        static public Type intptr_type;
+       static public Type uintptr_type;
        static public Type monitor_type;
        static public Type interlocked_type;
        static public Type runtime_field_handle_type;
@@ -269,6 +270,7 @@ public partial class TypeManager {
                builder_to_declspace = null;
                builder_to_member_cache = null;
                builder_to_ifaces = null;
+               builder_to_type_param = null;
                indexer_arguments = null;
                method_params = null;
                builder_to_method = null;
@@ -282,8 +284,6 @@ public partial class TypeManager {
 
 #if GMCS_SOURCE
                assembly_internals_vis_attrs = null;
-
-               CleanUpGenerics ();
 #endif
 
                TypeHandle.CleanUp ();
@@ -299,7 +299,7 @@ public partial class TypeManager {
 
                if (!(mi is MethodBase))
                        return false;
-               
+
                if (mi.Name != sig.name)
                        return false;
 
@@ -373,6 +373,7 @@ public partial class TypeManager {
                builder_to_declspace = new PtrHashtable ();
                builder_to_member_cache = new PtrHashtable ();
                builder_to_method = new PtrHashtable ();
+               builder_to_type_param = new PtrHashtable ();
                method_params = new PtrHashtable ();
                method_overrides = new PtrHashtable ();
                indexer_arguments = new PtrHashtable ();
@@ -385,8 +386,6 @@ public partial class TypeManager {
 
 #if GMCS_SOURCE
                assembly_internals_vis_attrs = new PtrHashtable ();
-               
-               InitGenerics ();
 #endif
 
                // to uncover regressions
@@ -438,6 +437,11 @@ public partial class TypeManager {
 
        public static MemberCache LookupMemberCache (Type t)
        {
+#if GMCS_SOURCE && MS_COMPATIBLE
+        if (t.IsGenericType && !t.IsGenericTypeDefinition)
+            t = t.GetGenericTypeDefinition ();
+#endif
+
                if (t is TypeBuilder) {
                        IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
                        if (container != null)
@@ -901,7 +905,7 @@ public partial class TypeManager {
                return GetMethod (t, name, args, false, report_errors);
        }
 
-       static MethodInfo GetMethod (Type t, string name, Type [] args)
+       public static MethodInfo GetMethod (Type t, string name, Type [] args)
        {
                return GetMethod (t, name, args, true);
        }
@@ -1020,6 +1024,7 @@ public partial class TypeManager {
                interlocked_type     = CoreLookupType ("System.Threading", "Interlocked");
                monitor_type         = CoreLookupType ("System.Threading", "Monitor");
                intptr_type          = CoreLookupType ("System", "IntPtr");
+               uintptr_type         = CoreLookupType ("System", "UIntPtr");
 
                attribute_type       = CoreLookupType ("System", "Attribute");
                attribute_usage_type = CoreLookupType ("System", "AttributeUsageAttribute");
@@ -1340,7 +1345,7 @@ public partial class TypeManager {
                                              MemberFilter filter, object criteria)
        {
 #if MS_COMPATIBLE && GMCS_SOURCE
-               if (t.IsGenericType)
+               if (t.IsGenericType && !t.IsGenericTypeDefinition)
                        t = t.GetGenericTypeDefinition ();
 #endif
 
@@ -1430,6 +1435,11 @@ public partial class TypeManager {
        {
                MemberCache cache;
 
+#if GMCS_SOURCE && MS_COMPATIBLE
+        if (t.IsGenericType && !t.IsGenericTypeDefinition)
+            t = t.GetGenericTypeDefinition();
+#endif
+
                //
                // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
                // and we can ask the DeclSpace for the MemberCache.
@@ -1465,7 +1475,7 @@ public partial class TypeManager {
                // a TypeBuilder array will return a Type, not a TypeBuilder,
                // and we can not call FindMembers on this type.
                //
-               if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
+               if (t.IsArray) { //  == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
                        used_cache = true;
                        return TypeHandle.ArrayType.MemberCache.FindMembers (
                                mt, bf, name, FilterWithClosure_delegate, null);
@@ -1483,8 +1493,9 @@ public partial class TypeManager {
                        used_cache = true;
                        return (MemberInfo []) list;
                }
+#endif
 
-               if (t.IsGenericType && (mt == MemberTypes.NestedType)) {
+               if (IsGenericType (t) && (mt == MemberTypes.NestedType)) {
                        //
                        // This happens if we're resolving a class'es base class and interfaces
                        // in TypeContainer.DefineType().  At this time, the types aren't
@@ -1495,7 +1506,6 @@ public partial class TypeManager {
                        used_cache = false;
                        return info;
                }
-#endif
 
                //
                // This call will always succeed.  There is exactly one TypeHandle instance per
@@ -1552,7 +1562,7 @@ public partial class TypeManager {
                        return true;
 
 #if MS_COMPATIBLE && GMCS_SOURCE
-               if (t.IsGenericParameter)
+               if (t.IsGenericParameter || t.IsGenericType)
                        return false;
 #endif
                return t.IsEnum;
@@ -1669,7 +1679,6 @@ public partial class TypeManager {
 
        public static bool IsSubclassOf (Type type, Type base_type)
        {
-#if GMCS_SOURCE
                TypeParameter tparam = LookupTypeParameter (type);
                TypeParameter pparam = LookupTypeParameter (base_type);
 
@@ -1680,10 +1689,9 @@ public partial class TypeManager {
                        return tparam.IsSubclassOf (base_type);
                }
 
-#if MS_COMPATIBLE
+#if MS_COMPATIBLE && GMCS_SOURCE
                if (type.IsGenericType)
                        type = type.GetGenericTypeDefinition ();
-#endif
 #endif
 
                if (type.IsSubclassOf (base_type))
@@ -1712,7 +1720,6 @@ public partial class TypeManager {
 
        public static bool IsFamilyAccessible (Type type, Type parent)
        {
-#if GMCS_SOURCE
                TypeParameter tparam = LookupTypeParameter (type);
                TypeParameter pparam = LookupTypeParameter (parent);
 
@@ -1722,7 +1729,6 @@ public partial class TypeManager {
 
                        return tparam.IsSubclassOf (parent);
                }
-#endif
 
                do {
                        if (IsInstantiationOfSameGenericType (type, parent))
@@ -2639,6 +2645,23 @@ public partial class TypeManager {
                return target_list;
        }
 
+#region Generics
+       // <remarks>
+       //   Tracks the generic parameters.
+       // </remarks>
+       static PtrHashtable builder_to_type_param;
+
+       public static void AddTypeParameter (Type t, TypeParameter tparam)
+       {
+               if (!builder_to_type_param.Contains (t))
+                       builder_to_type_param.Add (t, tparam);
+       }
+
+       public static TypeParameter LookupTypeParameter (Type t)
+       {
+               return (TypeParameter) builder_to_type_param [t];
+       }
+
        // This method always return false for non-generic compiler,
        // while Type.IsGenericParameter is returned if it is supported.
        public static bool IsGenericParameter (Type type)
@@ -2668,22 +2691,170 @@ public partial class TypeManager {
 #endif
        }
 
-#if !GMCS_SOURCE
+       public static bool IsGenericTypeDefinition (Type type)
+       {
+#if GMCS_SOURCE
+               return type.IsGenericTypeDefinition;
+#else
+               return false;
+#endif
+       }
+
+       public static bool ContainsGenericParameters (Type type)
+       {
+#if GMCS_SOURCE
+               return type.ContainsGenericParameters;
+#else
+               return false;
+#endif
+       }
+
+       public static FieldInfo GetGenericFieldDefinition (FieldInfo fi)
+       {
+#if GMCS_SOURCE
+               if (fi.DeclaringType.IsGenericTypeDefinition ||
+                   !fi.DeclaringType.IsGenericType)
+                       return fi;
+
+               Type t = fi.DeclaringType.GetGenericTypeDefinition ();
+               BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
+                       BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
+
+               foreach (FieldInfo f in t.GetFields (bf))
+                       if (f.MetadataToken == fi.MetadataToken)
+                               return f;
+#endif
+
+               return fi;
+       }
+
        public static bool IsEqual (Type a, Type b)
        {
-               return a.Equals (b);
+               if (a.Equals (b))
+                       return true;
+
+#if GMCS_SOURCE
+               if (a.IsGenericParameter && b.IsGenericParameter) {
+                       if (a.DeclaringMethod != b.DeclaringMethod &&
+                           (a.DeclaringMethod == null || b.DeclaringMethod == null))
+                               return false;
+                       return a.GenericParameterPosition == b.GenericParameterPosition;
+               }
+
+               if (a.IsArray && b.IsArray) {
+                       if (a.GetArrayRank () != b.GetArrayRank ())
+                               return false;
+                       return IsEqual (a.GetElementType (), b.GetElementType ());
+               }
+
+               if (a.IsByRef && b.IsByRef)
+                       return IsEqual (a.GetElementType (), b.GetElementType ());
+
+               if (a.IsGenericType && b.IsGenericType) {
+                       if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
+                               return false;
+
+                       Type[] aargs = a.GetGenericArguments ();
+                       Type[] bargs = b.GetGenericArguments ();
+
+                       if (aargs.Length != bargs.Length)
+                               return false;
+
+                       for (int i = 0; i < aargs.Length; i++) {
+                               if (!IsEqual (aargs [i], bargs [i]))
+                                       return false;
+                       }
+
+                       return true;
+               }
+#endif
+
+               return false;
        }
 
        public static Type DropGenericTypeArguments (Type t)
        {
+#if GMCS_SOURCE
+               if (!t.IsGenericType)
+                       return t;
+               // Micro-optimization: a generic typebuilder is always a generic type definition
+               if (t is TypeBuilder)
+                       return t;
+               return t.GetGenericTypeDefinition ();
+#else
                return t;
+#endif
        }
 
        public static MethodBase DropGenericMethodArguments (MethodBase m)
        {
+#if GMCS_SOURCE
+               if (m.IsGenericMethodDefinition)
+                       return m;
+               if (m.IsGenericMethod)
+                       return ((MethodInfo) m).GetGenericMethodDefinition ();
+               if (!m.DeclaringType.IsGenericType)
+                       return m;
+
+               Type t = m.DeclaringType.GetGenericTypeDefinition ();
+               BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic |
+                       BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
+
+#if MS_COMPATIBLE
+        return m;
+#endif
+
+               if (m is ConstructorInfo) {
+                       foreach (ConstructorInfo c in t.GetConstructors (bf))
+                               if (c.MetadataToken == m.MetadataToken)
+                                       return c;
+               } else {
+                       foreach (MethodBase mb in t.GetMethods (bf))
+                               if (mb.MetadataToken == m.MetadataToken)
+                                       return mb;
+               }
+#endif
+
                return m;
        }
+
+       public static Type[] GetGenericArguments (MethodInfo mi)
+       {
+#if GMCS_SOURCE
+               return mi.GetGenericArguments ();
+#else
+               return Type.EmptyTypes;
 #endif
+       }
+
+       public static Type[] GetTypeArguments (Type t)
+       {
+#if GMCS_SOURCE
+               DeclSpace tc = LookupDeclSpace (t);
+               if (tc != null) {
+                       if (!tc.IsGeneric)
+                               return Type.EmptyTypes;
+
+                       TypeParameter[] tparam = tc.TypeParameters;
+                       Type[] ret = new Type [tparam.Length];
+                       for (int i = 0; i < tparam.Length; i++) {
+                               ret [i] = tparam [i].Type;
+                               if (ret [i] == null)
+                                       throw new InternalErrorException ();
+                       }
+
+                       return ret;
+               } else
+                       return t.GetGenericArguments ();
+#else
+               throw new InternalErrorException ();
+#endif
+       }
+
+       public static bool HasGenericArguments (Type t)
+       {
+               return GetNumberOfTypeArguments (t) > 0;
+       }
 
        public static int GetNumberOfTypeArguments (Type t)
        {
@@ -2718,6 +2889,80 @@ public partial class TypeManager {
                return type.Equals (parent);
        }
 
+       /// <summary>
+       ///   Whether `mb' is a generic method definition.
+       /// </summary>
+       public static bool IsGenericMethodDefinition (MethodBase mb)
+       {
+#if GMCS_SOURCE
+               if (mb.DeclaringType is TypeBuilder) {
+                       IMethodData method = (IMethodData) builder_to_method [mb];
+                       if (method == null)
+                               return false;
+
+                       return method.GenericMethod != null;
+               }
+
+               return mb.IsGenericMethodDefinition;
+#else
+               return false;
+#endif
+       }
+
+       /// <summary>
+       ///   Whether `mb' is a generic method.
+       /// </summary>
+       public static bool IsGenericMethod (MethodBase mb)
+       {
+#if GMCS_SOURCE
+               if (mb.DeclaringType is TypeBuilder) {
+                       IMethodData method = (IMethodData) builder_to_method [mb];
+                       if (method == null)
+                               return false;
+
+                       return method.GenericMethod != null;
+               }
+
+               return mb.IsGenericMethod;
+#else
+               return false;
+#endif
+       }
+
+       public static bool IsNullableType (Type t)
+       {
+#if GMCS_SOURCE
+               return generic_nullable_type == DropGenericTypeArguments (t);
+#else
+               return false;
+#endif
+       }
+
+       public static bool IsNullableTypeOf (Type t, Type nullable)
+       {
+#if GMCS_SOURCE
+               if (!IsNullableType (t))
+                       return false;
+
+               return GetTypeArguments (t) [0] == nullable;
+#else
+               return false;
+#endif
+       }
+
+       public static bool IsNullableValueType (Type t)
+       {
+#if GMCS_SOURCE
+               if (!IsNullableType (t))
+                       return false;
+
+               return GetTypeArguments (t) [0].IsValueType;
+#else
+               return false;
+#endif
+       }
+#endregion
+
 #region MemberLookup implementation
        
        //
@@ -2796,7 +3041,10 @@ public partial class TypeManager {
 
                                if (ma == MethodAttributes.Public)
                                        return true;
-                               
+
+                               if (ma == MethodAttributes.PrivateScope)
+                                       return false;
+
                                if (ma == MethodAttributes.Private)
                                        return private_ok ||
                                                IsPrivateAccessible (invocation_type, m.DeclaringType) ||
@@ -2821,7 +3069,10 @@ public partial class TypeManager {
                                
                                if (fa == FieldAttributes.Public)
                                        return true;
-                               
+
+                               if (fa == FieldAttributes.PrivateScope)
+                                       return false;
+
                                if (fa == FieldAttributes.Private)
                                        return private_ok ||
                                                IsPrivateAccessible (invocation_type, m.DeclaringType) ||
@@ -3226,10 +3477,12 @@ public sealed class TypeHandle : IMemberContainer {
        public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
        {
                 MemberInfo [] members;
+
 #if GMCS_SOURCE
                if (type is GenericTypeParameterBuilder)
                        return MemberList.Empty;
 #endif
+
                if (mt == MemberTypes.Event)
                         members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
                 else