[mcs] Improve member lookup rules when type parameter has both non-object effective...
[mono.git] / mcs / mcs / ecore.cs
index 42eba97ee475763eb15186ea8a25bbe36fc1fca9..0937671675d24484f996e4146ae29a38c5ac1137 100644 (file)
@@ -841,22 +841,29 @@ namespace Mono.CSharp {
                public static Expression MemberLookup (IMemberContext rc, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
                {
                        var members = MemberCache.FindMembers (queried_type, name, false);
-                       if (members == null)
-                               return null;
 
-                       Expression expr;
-                       do {
-                               expr = MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
-                               if (expr != null)
-                                       return expr;
+                       if (members != null) {
+                               Expression expr;
+                               do {
+                                       expr = MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
+                                       if (expr != null)
+                                               return expr;
 
-                               if (members [0].DeclaringType.BaseType == null)
-                                       members = null;
-                               else
-                                       members = MemberCache.FindMembers (members [0].DeclaringType.BaseType, name, false);
-                       } while (members != null);
+                                       if (members [0].DeclaringType.BaseType == null)
+                                               members = null;
+                                       else
+                                               members = MemberCache.FindMembers (members [0].DeclaringType.BaseType, name, false);
+                               } while (members != null);
+                       }
 
-                       return expr;
+                       var tps = queried_type as TypeParameterSpec;
+                       if (tps != null) {
+                               members = MemberCache.FindInterfaceMembers (tps, name);
+                               if (members != null)
+                                       return MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
+                       }
+
+                       return null;
                }
 
                public static Expression MemberLookupToExpression (IMemberContext rc, IList<MemberSpec> members, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
@@ -901,15 +908,6 @@ namespace Mono.CSharp {
 
                                if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
                                        if (member is MethodSpec) {
-                                               //
-                                               // Interface members that are hidden by class members are removed from the set. This
-                                               // step only has an effect if T is a type parameter and T has both an effective base 
-                                               // class other than object and a non-empty effective interface set
-                                               //
-                                               var tps = queried_type as TypeParameterSpec;
-                                               if (tps != null && tps.HasTypeConstraint)
-                                                       members = RemoveHiddenTypeParameterMethods (members);
-
                                                return new MethodGroupExpr (members, queried_type, loc);
                                        }
 
@@ -959,57 +957,6 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               static IList<MemberSpec> RemoveHiddenTypeParameterMethods (IList<MemberSpec> members)
-               {
-                       if (members.Count < 2)
-                               return members;
-
-                       //
-                       // If M is a method, then all non-method members declared in an interface declaration
-                       // are removed from the set, and all methods with the same signature as M declared in
-                       // an interface declaration are removed from the set
-                       //
-
-                       bool copied = false;
-                       for (int i = 0; i < members.Count; ++i) {
-                               var method = members[i] as MethodSpec;
-                               if (method == null) {
-                                       if (!copied) {
-                                               copied = true;
-                                               members = new List<MemberSpec> (members);
-                                       } 
-                                       
-                                       members.RemoveAt (i--);
-                                       continue;
-                               }
-
-                               if (!method.DeclaringType.IsInterface)
-                                       continue;
-
-                               for (int ii = 0; ii < members.Count; ++ii) {
-                                       var candidate = members[ii] as MethodSpec;
-                                       if (candidate == null || !candidate.DeclaringType.IsClass)
-                                               continue;
-
-                                       if (!TypeSpecComparer.Override.IsEqual (candidate.Parameters, method.Parameters))
-                                               continue;
-
-                                       if (!AParametersCollection.HasSameParameterDefaults (candidate.Parameters, method.Parameters))
-                                               continue;
-
-                                       if (!copied) {
-                                               copied = true;
-                                               members = new List<MemberSpec> (members);
-                                       }
-
-                                       members.RemoveAt (i--);
-                                       break;
-                               }
-                       }
-
-                       return members;
-               }
-
                protected static void Error_NamedArgument (NamedArgument na, Report Report)
                {
                        Report.Error (1742, na.Location, "An element access expression cannot use named argument");
@@ -3776,7 +3723,7 @@ namespace Mono.CSharp {
                // For extension methodgroup we are not looking for base members but parent
                // namespace extension methods
                //
-               public override IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
+               public override IList<MemberSpec> GetBaseMembers (TypeSpec type)
                {
                        // TODO: candidates are null only when doing error reporting, that's
                        // incorrect. We have to discover same extension methods in error mode
@@ -4233,9 +4180,19 @@ namespace Mono.CSharp {
 
                #region IBaseMembersProvider Members
 
-               public virtual IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
+               public virtual IList<MemberSpec> GetBaseMembers (TypeSpec type)
                {
-                       return baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
+                       var baseType = type.BaseType;
+                       
+                       IList<MemberSpec> members = baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
+
+                       if (members == null && !type.IsInterface) {
+                               var tps = queried_type as TypeParameterSpec;
+                               if (tps != null)
+                                       members = MemberCache.FindInterfaceMembers (tps, Methods [0].Name);
+                       }
+
+                       return members;
                }
 
                public IParametersMember GetOverrideMemberParameters (MemberSpec member)
@@ -5632,7 +5589,7 @@ namespace Mono.CSharp {
                                                // Restore expanded arguments
                                                candidate_args = args;
                                        }
-                               } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null);
+                               } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType)) != null);
 
                                //
                                // We've found exact match