Implement partial generic methods
[mono.git] / mcs / mcs / membercache.cs
index e59b6d31fe0e0ed5def30b4817185b3d65ed5348..de1ef82c7fd610f50f3cce042a8d9897e2bfeac8 100644 (file)
@@ -73,15 +73,6 @@ namespace Mono.CSharp {
                public readonly TypeSpec MemberType;
                public readonly int Arity; // -1 to ignore the check
 
-               private MemberFilter (string name, MemberKind kind)
-               {
-                       Name = name;
-                       Kind = kind;
-                       Parameters = null;
-                       MemberType = null;
-                       Arity = -1;
-               }
-
                public MemberFilter (MethodSpec m)
                {
                        Name = m.Name;
@@ -249,6 +240,8 @@ namespace Mono.CSharp {
                // contain all base interface members, so the Lookup code
                // can use simple inheritance rules.
                //
+               // Does not work recursively because of generic interfaces
+               //
                public void AddInterface (TypeSpec iface)
                {
                        var cache = iface.MemberCache;
@@ -267,6 +260,13 @@ namespace Mono.CSharp {
                                }
 
                                foreach (var ce in entry.Value) {
+                                       //
+                                       // When two or more different base interfaces implemenent common
+                                       // interface
+                                       //
+                                       // I : IA, IFoo
+                                       // IA : IFoo
+                                       //
                                        if (list.Contains (ce))
                                                continue;
 
@@ -274,12 +274,6 @@ namespace Mono.CSharp {
                                                member_hash[entry.Key] = list;
                                }
                        }
-
-                       // Add also all base interfaces
-                       if (iface.Interfaces != null) {
-                               foreach (var base_iface in iface.Interfaces)
-                                       AddInterface (base_iface);
-                       }
                }
 
                public void AddMember (InterfaceMemberBase imb, string exlicitName, MemberSpec ms)
@@ -305,13 +299,14 @@ namespace Mono.CSharp {
                        if (member.Kind == MemberKind.Operator) {
                                var dt = member.DeclaringType;
 
+
                                //
                                // Some core types have user operators but they cannot be used like normal
                                // user operators as they are predefined and therefore having different
                                // rules (e.g. binary operators) by not setting the flag we hide them for
                                // user conversions
                                //
-                               if (!BuiltinTypeSpec.IsPrimitiveType (dt)) {
+                               if (!BuiltinTypeSpec.IsPrimitiveType (dt) || dt.BuiltinType == BuiltinTypeSpec.Type.Char) {
                                        switch (dt.BuiltinType) {
                                        case BuiltinTypeSpec.Type.String:
                                        case BuiltinTypeSpec.Type.Delegate:
@@ -444,12 +439,15 @@ namespace Mono.CSharp {
                // A special method to work with member lookup only. It returns a list of all members named @name
                // starting from @container. It's very performance sensitive
                //
-               public static IList<MemberSpec> FindMembers (TypeSpec container, string name, bool declaredOnly)
+               // declaredOnlyClass cannot be used interfaces. Manual filtering is required because names are
+               // compacted
+               //
+               public static IList<MemberSpec> FindMembers (TypeSpec container, string name, bool declaredOnlyClass)
                {
                        IList<MemberSpec> applicable;
 
                        do {
-                               if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnly)
+                               if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnlyClass)
                                        return applicable;
 
                                container = container.BaseType;
@@ -797,7 +795,7 @@ namespace Mono.CSharp {
                        while (true) {
                                foreach (var entry in abstract_type.MemberCache.member_hash) {
                                        foreach (var name_entry in entry.Value) {
-                                               if ((name_entry.Modifiers & Modifiers.ABSTRACT) == 0)
+                                               if ((name_entry.Modifiers & (Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != Modifiers.ABSTRACT)
                                                        continue;
 
                                                if (name_entry.Kind != MemberKind.Method)
@@ -846,6 +844,12 @@ namespace Mono.CSharp {
                                                if ((item.Modifiers & (Modifiers.OVERRIDE | Modifiers.VIRTUAL)) == 0)
                                                        continue;
 
+                                               //
+                                               // Abstract override does not override anything
+                                               //
+                                               if ((item.Modifiers & Modifiers.ABSTRACT) != 0)
+                                                       continue;
+
                                                if (filter.Equals (item)) {
                                                        --not_implemented_count;
                                                        abstract_methods [i] = null;
@@ -894,7 +898,7 @@ namespace Mono.CSharp {
                                return IndexerNameAlias;
 
                        if (mc is Constructor)
-                               return Constructor.ConstructorName;
+                               return mc.IsStatic ? Constructor.TypeConstructorName : Constructor.ConstructorName;
 
                        return mc.MemberName.Name;
                }
@@ -905,7 +909,7 @@ namespace Mono.CSharp {
                public static IList<MemberSpec> GetUserOperator (TypeSpec container, Operator.OpType op, bool declaredOnly)
                {
                        IList<MemberSpec> found = null;
-
+                       bool shared_list = true;
                        IList<MemberSpec> applicable;
                        do {
                                var mc = container.MemberCache;
@@ -935,10 +939,13 @@ namespace Mono.CSharp {
                                                                        found = new List<MemberSpec> ();
                                                                        found.Add (applicable[i]);
                                                                } else {
-                                                                       var prev = found as List<MemberSpec>;
-                                                                       if (prev == null) {
+                                                                       List<MemberSpec> prev;
+                                                                       if (shared_list) {
+                                                                               shared_list = false;
                                                                                prev = new List<MemberSpec> (found.Count + 1);
                                                                                prev.AddRange (found);
+                                                                       } else {
+                                                                               prev = (List<MemberSpec>) found;
                                                                        }
 
                                                                        prev.Add (applicable[i]);
@@ -947,12 +954,16 @@ namespace Mono.CSharp {
                                                } else {
                                                        if (found == null) {
                                                                found = applicable;
+                                                               shared_list = true;
                                                        } else {
-                                                               var merged = found as List<MemberSpec>;
-                                                               if (merged == null) {
+                                                               List<MemberSpec> merged;
+                                                               if (shared_list) {
+                                                                       shared_list = false;
                                                                        merged = new List<MemberSpec> (found.Count + applicable.Count);
                                                                        merged.AddRange (found);
                                                                        found = merged;
+                                                               } else {
+                                                                       merged = (List<MemberSpec>) found;
                                                                }
 
                                                                merged.AddRange (applicable);
@@ -1163,8 +1174,9 @@ namespace Mono.CSharp {
                        if (container.BaseType == null) {
                                locase_members = new Dictionary<string, MemberSpec[]> (member_hash.Count); // StringComparer.OrdinalIgnoreCase);
                        } else {
-                               container.BaseType.MemberCache.VerifyClsCompliance (container.BaseType, report);
-                               locase_members = new Dictionary<string, MemberSpec[]> (container.BaseType.MemberCache.locase_members); //, StringComparer.OrdinalIgnoreCase);
+                               var btype = container.BaseType.GetDefinition ();
+                               btype.MemberCache.VerifyClsCompliance (btype, report);
+                               locase_members = new Dictionary<string, MemberSpec[]> (btype.MemberCache.locase_members); //, StringComparer.OrdinalIgnoreCase);
                        }
 
                        var is_imported_type = container.MemberDefinition.IsImported;
@@ -1354,8 +1366,10 @@ namespace Mono.CSharp {
                                                type_a = parameters.Types [ii];
                                                type_b = p_types [ii];
 
-                                               if ((pd.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF) !=
-                                                       (parameters.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF))
+                                               var a_byref = (pd.FixedParameters[ii].ModFlags & Parameter.Modifier.RefOutMask) != 0;
+                                               var b_byref = (parameters.FixedParameters[ii].ModFlags & Parameter.Modifier.RefOutMask) != 0;
+
+                                               if (a_byref != b_byref)
                                                        break;
 
                                        } while (TypeSpecComparer.Override.IsEqual (type_a, type_b) && ii-- != 0);
@@ -1374,7 +1388,9 @@ namespace Mono.CSharp {
                                        //
                                        if (pd != null && member is MethodCore) {
                                                ii = method_param_count;
-                                               while (ii-- != 0 && parameters.FixedParameters[ii].ModFlags == pd.FixedParameters[ii].ModFlags &&
+                                               while (ii-- != 0 &&
+                                                       (parameters.FixedParameters[ii].ModFlags & Parameter.Modifier.ModifierMask) ==
+                                                       (pd.FixedParameters[ii].ModFlags & Parameter.Modifier.ModifierMask) &&
                                                        parameters.ExtensionMethodType == pd.ExtensionMethodType) ;
 
                                                if (ii >= 0) {
@@ -1429,9 +1445,12 @@ namespace Mono.CSharp {
                                                                        "A partial method declaration and partial method implementation must be both `static' or neither");
                                                        }
 
-                                                       Report.SymbolRelatedToPreviousError (ce);
-                                                       Report.Error (764, member.Location,
-                                                               "A partial method declaration and partial method implementation must be both `unsafe' or neither");
+                                                       if ((method_a.ModFlags & Modifiers.UNSAFE) != (method_b.ModFlags & Modifiers.UNSAFE)) {
+                                                               Report.SymbolRelatedToPreviousError (ce);
+                                                               Report.Error (764, member.Location,
+                                                                       "A partial method declaration and partial method implementation must be both `unsafe' or neither");
+                                                       }
+
                                                        return false;
                                                }