[mcs] Improve member lookup rules when type parameter has both non-object effective...
[mono.git] / mcs / mcs / membercache.cs
index 8ada0a97071a327cd2c8433a09eb654d904633bd..27b7f586932c7d01e355f5bc2745512d5cb07a1a 100644 (file)
@@ -406,8 +406,13 @@ namespace Mono.CSharp {
 
                public static MemberSpec FindMember (TypeSpec container, MemberFilter filter, BindingRestriction restrictions)
                {
+                       if (filter.Kind == MemberKind.Method && container.Kind == MemberKind.TypeParameter && filter.Parameters == null)
+                               throw new NotSupportedException ("type parameters methods cannot be lookup up due to two stage setup");
+
+                       IList<MemberSpec> applicable;
+                       var top_container = container;
+
                        do {
-                               IList<MemberSpec> applicable;
                                if (container.MemberCache.member_hash.TryGetValue (filter.Name, out applicable)) {
                                        // Start from the end because interface members are in reverse order
                                        for (int i = applicable.Count - 1; i >= 0; i--) {
@@ -438,6 +443,26 @@ namespace Mono.CSharp {
                                container = container.BaseType;
                        } while (container != null);
 
+                       var tps = top_container as TypeParameterSpec;
+                       if (tps != null && tps.InterfaceCache != null) {
+                               if (tps.InterfaceCache.member_hash.TryGetValue (filter.Name, out applicable)) {
+                                       for (int i = applicable.Count - 1; i >= 0; i--) {
+                                               var entry = applicable [i];
+
+                                               if ((restrictions & BindingRestriction.NoAccessors) != 0 && entry.IsAccessor)
+                                                       continue;
+
+                                               if ((restrictions & BindingRestriction.OverrideOnly) != 0 && (entry.Modifiers & Modifiers.OVERRIDE) == 0)
+                                                       continue;
+
+                                               if (!filter.Equals (entry))
+                                                       continue;
+
+                                               return entry;
+                                       }
+                               }
+                       }
+
                        return null;
                }
 
@@ -450,9 +475,9 @@ namespace Mono.CSharp {
                //
                public static IList<MemberSpec> FindMembers (TypeSpec container, string name, bool declaredOnlyClass)
                {
-                       IList<MemberSpec> applicable;
-
                        do {
+                               IList<MemberSpec> applicable;
+                               
                                if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnlyClass)
                                        return applicable;
 
@@ -462,6 +487,17 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               public static IList<MemberSpec> FindInterfaceMembers (TypeParameterSpec typeParameter, string name)
+               {
+                       if (typeParameter.InterfaceCache != null) {
+                               IList<MemberSpec> applicable;
+                               typeParameter.InterfaceCache.member_hash.TryGetValue (name, out applicable);
+                               return applicable;
+                       }
+
+                       return null;
+               }
+
                //
                // Finds the nested type in container
                //