LookupExtensionMethod() public method

public LookupExtensionMethod ( System.TypeSpec extensionType, string name, int arity, NamespaceEntry &scope ) : IList
extensionType System.TypeSpec
name string
arity int
scope NamespaceEntry
return IList
Example #1
0
        protected override Expression DoResolve(ResolveContext ec)
        {
            eclass = ExprClass.PropertyAccess;

            bool must_do_cs1540_check = false;
            ec.Report.DisableReporting ();
            bool res = ResolveGetter (ec, ref must_do_cs1540_check);
            ec.Report.EnableReporting ();

            if (!res) {
                if (InstanceExpression != null) {
                    TypeSpec expr_type = InstanceExpression.Type;
                    ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, 0, loc);
                    if (ex_method_lookup != null) {
                        ex_method_lookup.ExtensionExpression = InstanceExpression;
                        ex_method_lookup.SetTypeArguments (ec, targs);
                        return ex_method_lookup.Resolve (ec);
                    }
                }

                ResolveGetter (ec, ref must_do_cs1540_check);
                return null;
            }

            if (!InstanceResolve (ec, false, must_do_cs1540_check))
                return null;

            //
            // Only base will allow this invocation to happen.
            //
            if (IsBase && spec.IsAbstract) {
                Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (spec));
            }

            if (spec.MemberType.IsPointer && !ec.IsUnsafe){
                UnsafeError (ec, loc);
            }

            if (!ec.IsObsolete) {
                ObsoleteAttribute oa = spec.GetAttributeObsolete ();
                if (oa != null)
                    AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
            }

            return this;
        }
Example #2
0
        /// <summary>
        ///   Find the Applicable Function Members (7.4.2.1)
        ///
        ///   me: Method Group expression with the members to select.
        ///       it might contain constructors or methods (or anything
        ///       that maps to a method).
        ///
        ///   Arguments: ArrayList containing resolved Argument objects.
        ///
        ///   loc: The location if we want an error to be reported, or a Null
        ///        location for "probing" purposes.
        ///
        ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
        ///            that is the best match of me on Arguments.
        ///
        /// </summary>
        public virtual MethodGroupExpr OverloadResolve(ResolveContext ec, ref Arguments Arguments,
            bool may_fail, Location loc)
        {
            var candidates = new List<MethodSpec> (2);
            List<MethodSpec> params_candidates = null;

            int arg_count = Arguments != null ? Arguments.Count : 0;
            Dictionary<MethodSpec, Arguments> candidates_expanded = null;
            Arguments candidate_args = Arguments;

            if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
                if (!may_fail)
                    ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
                return null;
            }

            //
            // Enable message recording, it's used mainly by lambda expressions
            //
            var msg_recorder = new SessionReportPrinter ();
            var prev_recorder = ec.Report.SetPrinter (msg_recorder);

            do {
                //
                // Methods in a base class are not candidates if any method in a derived
                // class is applicable
                //
                int best_candidate_rate = int.MaxValue;

                foreach (var member in Methods) {
                    var m = member as MethodSpec;
                    if (m == null) {
                        // TODO: It's wrong when non-member is before applicable method
                        // TODO: Should report only when at least 1 from the batch is applicable
                        if (candidates.Count != 0) {
                            ec.Report.SymbolRelatedToPreviousError (candidates [0]);
                            ec.Report.SymbolRelatedToPreviousError (member);
                            ec.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'",
                                candidates[0].GetSignatureForError (), member.GetSignatureForError ());
                        }
                        continue;
                    }

                    //
                    // Check if candidate is applicable (section 14.4.2.1)
                    //
                    bool params_expanded_form = false;
                    int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref m, ref params_expanded_form);

                    if (candidate_rate < best_candidate_rate) {
                        best_candidate_rate = candidate_rate;
                        best_candidate = m;
                    }

                    if (params_expanded_form) {
                        if (params_candidates == null)
                            params_candidates = new List<MethodSpec> (2);
                        params_candidates.Add (m);
                    }

                    if (candidate_args != Arguments) {
                        if (candidates_expanded == null)
                            candidates_expanded = new Dictionary<MethodSpec, Arguments> (2);

                        candidates_expanded.Add (m, candidate_args);
                        candidate_args = Arguments;
                    }

                    if (candidate_rate != 0 || has_inaccessible_candidates_only) {
                        if (msg_recorder != null)
                            msg_recorder.EndSession ();
                        continue;
                    }

                    msg_recorder = null;
                    candidates.Add (m);
                }
            } while (candidates.Count == 0 && GetBaseTypeMethods (ec));

            ec.Report.SetPrinter (prev_recorder);
            if (msg_recorder != null && !msg_recorder.IsEmpty) {
                if (!may_fail)
                    msg_recorder.Merge (prev_recorder);

                return null;
            }

            int candidate_top = candidates.Count;
            if (candidate_top == 0) {
                //
                // When we found a top level method which does not match and it's
                // not an extension method. We start extension methods lookup from here
                //
                if (InstanceExpression != null) {
                    var first = Methods.First ();
                    var arity = type_arguments == null ? -1 : type_arguments.Count;
                    ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, first.Name, arity, loc);
                    if (ex_method_lookup != null) {
                        ex_method_lookup.ExtensionExpression = InstanceExpression;
                        ex_method_lookup.SetTypeArguments (ec, type_arguments);
                        return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
                    }
                }

                if (may_fail)
                    return null;

                //
                // Okay so we have failed to find exact match so we
                // return error info about the closest match
                //
                if (best_candidate != null) {
                    if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
                        return null;

                    bool params_expanded = params_candidates != null && params_candidates.Contains (best_candidate);
                    if (NoExactMatch (ec, ref Arguments, params_expanded))
                        return null;
                }

                //
                // We failed to find any method with correct argument count
                //
                if (Methods.First ().Kind == MemberKind.Constructor) {
                    ec.Report.SymbolRelatedToPreviousError (queried_type);
                    ec.Report.Error (1729, loc,
                        "The type `{0}' does not contain a constructor that takes `{1}' arguments",
                        TypeManager.CSharpName (queried_type), arg_count.ToString ());
                } else {
                    Error_ArgumentCountWrong (ec, arg_count);
                }

                return null;
            }

            if (arg_count != 0 && Arguments.HasDynamic) {
                best_candidate = null;
                return this;
            }

            //
            // Now we actually find the best method
            //
            best_candidate = candidates [0];
            bool method_params = params_candidates != null && params_candidates.Contains (best_candidate);

            for (int ix = 1; ix < candidate_top; ix++) {
                var candidate = candidates [ix];

                if (candidate == best_candidate)
                    continue;

                bool cand_params = params_candidates != null && params_candidates.Contains (candidate);

                if (candidates_expanded != null && candidates_expanded.ContainsKey (candidate)) {
                    candidate_args = candidates_expanded[candidate];
                    arg_count = candidate_args.Count;
                }

                if (BetterFunction (ec, candidate_args, arg_count,
                    candidate, cand_params,
                    best_candidate, method_params)) {
                    best_candidate = candidate;
                    method_params = cand_params;
                }

                if (candidate_args != Arguments) {
                    candidate_args = Arguments;
                    arg_count = candidate_args != null ? candidate_args.Count : 0;
                }
            }

            if (candidates_expanded != null && candidates_expanded.ContainsKey (best_candidate)) {
                candidate_args = candidates_expanded[best_candidate];
                arg_count = candidate_args.Count;
            }

            //
            // Now check that there are no ambiguities i.e the selected method
            // should be better than all the others
            //
            MethodSpec ambiguous = null;
            for (int ix = 1; ix < candidate_top; ix++) {
                var candidate = candidates [ix];

                if (candidate == best_candidate)
                    continue;

                bool cand_params = params_candidates != null && params_candidates.Contains (candidate);
                if (!BetterFunction (ec, candidate_args, arg_count,
                    best_candidate, method_params,
                    candidate, cand_params))
                {
                    if (!may_fail)
                        ec.Report.SymbolRelatedToPreviousError (candidate);
                    ambiguous = candidate;
                }
            }

            if (ambiguous != null) {
                Error_AmbiguousCall (ec, ambiguous);
                return this;
            }

            //
            // And now check if the arguments are all
            // compatible, perform conversions if
            // necessary etc. and return if everything is
            // all right
            //
            if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
                method_params, may_fail, loc))
                return null;

            if (best_candidate == null)
                return null;

            if (best_candidate.IsGeneric) {
                ConstraintChecker.CheckAll (best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments,
                    best_candidate.Constraints, loc, ec.Report);
            }

            //
            // Check ObsoleteAttribute on the best method
            //
            ObsoleteAttribute oa = best_candidate.GetAttributeObsolete ();
            if (oa != null && !ec.IsObsolete)
                AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);

            best_candidate.MemberDefinition.SetIsUsed ();

            Arguments = candidate_args;
            return this;
        }
		public override Expression DoResolve (ResolveContext ec)
		{
			// Don't resolve already resolved expression
			if (eclass != ExprClass.Invalid)
				return this;
			
			Expression expr_resolved = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
			if (expr_resolved == null)
				return null;

			//
			// Next, evaluate all the expressions in the argument list
			//
			bool dynamic_arg = false;
			if (arguments != null && !arguments_resolved)
				arguments.Resolve (ec, out dynamic_arg);

			Type expr_type = expr_resolved.Type;
			mg = expr_resolved as MethodGroupExpr;

			if (dynamic_arg || TypeManager.IsDynamicType (expr_type)) {
				Arguments args;
				DynamicMemberBinder dmb = expr_resolved as DynamicMemberBinder;
				if (dmb != null) {
					args = dmb.Arguments;
					if (arguments != null)
						args.AddRange (arguments);
				} else if (mg == null) {
					if (arguments == null)
						args = new Arguments (1);
					else
						args = arguments;

					args.Insert (0, new Argument (expr_resolved));
					expr = null;
				} else {
					if (mg.IsBase) {
						ec.Report.Error (1971, loc,
							"The base call to method `{0}' cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access",
							mg.Name);
						return null;
					}

					args = arguments;

					if (mg.IsStatic != mg.IsInstance) {
						if (args == null)
							args = new Arguments (1);

						if (mg.IsStatic) {
							args.Insert (0, new Argument (new TypeOf (new TypeExpression (mg.DeclaringType, loc), loc).Resolve (ec), Argument.AType.DynamicStatic));
						} else {
							MemberAccess ma = expr as MemberAccess;
							if (ma != null)
								args.Insert (0, new Argument (ma.Left.Resolve (ec)));
							else
								args.Insert (0, new Argument (new This (loc).Resolve (ec)));
						}
					}
				}

				return new DynamicInvocation (expr as ATypeNameExpression, args, loc).Resolve (ec);
			}

			if (mg == null) {
				if (expr_type != null && TypeManager.IsDelegateType (expr_type)){
					return (new DelegateInvocation (
						expr_resolved, arguments, loc)).Resolve (ec);
				}

				MemberExpr me = expr_resolved as MemberExpr;
				if (me == null) {
					expr_resolved.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup, loc);
					return null;
				}
				
				mg = ec.LookupExtensionMethod (me.Type, me.Name, loc);
				if (mg == null) {
					ec.Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate",
						expr_resolved.GetSignatureForError ());
					return null;
				}

				((ExtensionMethodGroupExpr)mg).ExtensionExpression = me.InstanceExpression;
			}

			mg = DoResolveOverload (ec);
			if (mg == null)
				return null;

			MethodInfo method = (MethodInfo)mg;
			if (method != null) {
				type = TypeManager.TypeToCoreType (method.ReturnType);

				// TODO: this is a copy of mg.ResolveMemberAccess method
				Expression iexpr = mg.InstanceExpression;
				if (method.IsStatic) {
					if (iexpr == null ||
						iexpr is This || iexpr is EmptyExpression ||
						mg.IdenticalTypeName) {
						mg.InstanceExpression = null;
					} else {
						MemberExpr.error176 (ec, loc, mg.GetSignatureForError ());
						return null;
					}
				} else {
					if (iexpr == null || iexpr == EmptyExpression.Null) {
						SimpleName.Error_ObjectRefRequired (ec, loc, mg.GetSignatureForError ());
					}
				}
			}

			if (type.IsPointer){
				if (!ec.IsUnsafe){
					UnsafeError (ec, loc);
					return null;
				}
			}
			
			//
			// Only base will allow this invocation to happen.
			//
			if (mg.IsBase && method.IsAbstract){
				Error_CannotCallAbstractBase (ec, TypeManager.CSharpSignature (method));
				return null;
			}

			if (arguments == null && method.DeclaringType == TypeManager.object_type && method.Name == Destructor.MetadataName) {
				if (mg.IsBase)
					ec.Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor");
				else
					ec.Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available");
				return null;
			}

			IsSpecialMethodInvocation (ec, method, loc);
			
			if (mg.InstanceExpression != null)
				mg.InstanceExpression.CheckMarshalByRefAccess (ec);

			eclass = ExprClass.Value;
			return this;
		}
		Expression DoResolve (ResolveContext ec, Expression right_side)
		{
			if (type != null)
				throw new Exception ();

			//
			// Resolve the expression with flow analysis turned off, we'll do the definite
			// assignment checks later.  This is because we don't know yet what the expression
			// will resolve to - it may resolve to a FieldExpr and in this case we must do the
			// definite assignment check on the actual field and not on the whole struct.
			//

			SimpleName original = expr as SimpleName;
			Expression expr_resolved = expr.Resolve (ec,
				ResolveFlags.VariableOrValue | ResolveFlags.Type |
				ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis);

			if (expr_resolved == null)
				return null;

			string LookupIdentifier = MemberName.MakeName (Name, targs);

			Namespace ns = expr_resolved as Namespace;
			if (ns != null) {
				FullNamedExpression retval = ns.Lookup (ec.Compiler, LookupIdentifier, loc);

				if (retval == null)
					ns.Error_NamespaceDoesNotExist (loc, LookupIdentifier, ec.Report);
				else if (targs != null)
					retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (ec, false);

				return retval;
			}

			Type expr_type = expr_resolved.Type;
			if (TypeManager.IsDynamicType (expr_type)) {
				Arguments args = new Arguments (2);
				args.Add (new Argument (expr_resolved.Resolve (ec)));
				if (right_side != null)
					args.Add (new Argument (right_side));

				return new DynamicMemberBinder (right_side != null, Name, args, loc).Resolve (ec);
			}

			if (expr_type.IsPointer || expr_type == TypeManager.void_type ||
				expr_type == TypeManager.null_type || expr_type == InternalType.AnonymousMethod) {
				Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type);
				return null;
			}

			Constant c = expr_resolved as Constant;
			if (c != null && c.GetValue () == null) {
				ec.Report.Warning (1720, 1, loc, "Expression will always cause a `{0}'",
					"System.NullReferenceException");
			}

			if (targs != null) {
				if (!targs.Resolve (ec))
					return null;
			}

			Expression member_lookup;
			member_lookup = MemberLookup (ec.Compiler,
				ec.CurrentType, expr_type, expr_type, Name, loc);

			if (member_lookup == null && targs != null) {
				member_lookup = MemberLookup (ec.Compiler,
					ec.CurrentType, expr_type, expr_type, LookupIdentifier, loc);
			}

			if (member_lookup == null) {
				ExprClass expr_eclass = expr_resolved.eclass;

				//
				// Extension methods are not allowed on all expression types
				//
				if (expr_eclass == ExprClass.Value || expr_eclass == ExprClass.Variable ||
					expr_eclass == ExprClass.IndexerAccess || expr_eclass == ExprClass.PropertyAccess ||
					expr_eclass == ExprClass.EventAccess) {
					ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, loc);
					if (ex_method_lookup != null) {
						ex_method_lookup.ExtensionExpression = expr_resolved;

						if (targs != null) {
							ex_method_lookup.SetTypeArguments (ec, targs);
						}

						return ex_method_lookup.DoResolve (ec);
					}
				}

				expr = expr_resolved;
				member_lookup = Error_MemberLookupFailed (ec,
					ec.CurrentType, expr_type, expr_type, Name, null,
					AllMemberTypes, AllBindingFlags);
				if (member_lookup == null)
					return null;
			}

			TypeExpr texpr = member_lookup as TypeExpr;
			if (texpr != null) {
				if (!(expr_resolved is TypeExpr) && 
				    (original == null || !original.IdenticalNameAndTypeName (ec, expr_resolved, loc))) {
					ec.Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead",
						Name, member_lookup.GetSignatureForError ());
					return null;
				}

				if (!texpr.CheckAccessLevel (ec.MemberContext)) {
					ec.Report.SymbolRelatedToPreviousError (member_lookup.Type);
					ErrorIsInaccesible (loc, TypeManager.CSharpName (member_lookup.Type), ec.Report);
					return null;
				}

				GenericTypeExpr ct = expr_resolved as GenericTypeExpr;
				if (ct != null) {
					//
					// When looking up a nested type in a generic instance
					// via reflection, we always get a generic type definition
					// and not a generic instance - so we have to do this here.
					//
					// See gtest-172-lib.cs and gtest-172.cs for an example.
					//

					TypeArguments nested_targs;
					if (HasTypeArguments) {
						nested_targs = ct.TypeArguments.Clone ();
						nested_targs.Add (targs);
					} else {
						nested_targs = ct.TypeArguments;
					}

					ct = new GenericTypeExpr (member_lookup.Type, nested_targs, loc);

					return ct.ResolveAsTypeStep (ec, false);
				}

				return member_lookup;
			}

			MemberExpr me = (MemberExpr) member_lookup;
			me = me.ResolveMemberAccess (ec, expr_resolved, loc, original);
			if (me == null)
				return null;

			if (targs != null) {
				me.SetTypeArguments (ec, targs);
			}

			if (original != null && !TypeManager.IsValueType (expr_type)) {
				if (me.IsInstance) {
					LocalVariableReference var = expr_resolved as LocalVariableReference;
					if (var != null && !var.VerifyAssigned (ec))
						return null;
				}
			}

			// The following DoResolve/DoResolveLValue will do the definite assignment
			// check.

			if (right_side != null)
				return me.DoResolveLValue (ec, right_side);
			else
				return me.DoResolve (ec);
		}
Example #5
0
		/// <summary>
		///   Find the Applicable Function Members (7.4.2.1)
		///
		///   me: Method Group expression with the members to select.
		///       it might contain constructors or methods (or anything
		///       that maps to a method).
		///
		///   Arguments: ArrayList containing resolved Argument objects.
		///
		///   loc: The location if we want an error to be reported, or a Null
		///        location for "probing" purposes.
		///
		///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
		///            that is the best match of me on Arguments.
		///
		/// </summary>
		public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments Arguments,
			bool may_fail, Location loc)
		{
			bool method_params = false;
			Type applicable_type = null;
			ArrayList candidates = new ArrayList (2);
			ArrayList candidate_overrides = null;

			//
			// Used to keep a map between the candidate
			// and whether it is being considered in its
			// normal or expanded form
			//
			// false is normal form, true is expanded form
			//
			Hashtable candidate_to_form = null;
			Hashtable candidates_expanded = null;
			Arguments candidate_args = Arguments;

			int arg_count = Arguments != null ? Arguments.Count : 0;

			if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
				if (!may_fail)
					ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
				return null;
			}

			int nmethods = Methods.Length;

			if (!IsBase) {
				//
				// Methods marked 'override' don't take part in 'applicable_type'
				// computation, nor in the actual overload resolution.
				// However, they still need to be emitted instead of a base virtual method.
				// So, we salt them away into the 'candidate_overrides' array.
				//
				// In case of reflected methods, we replace each overriding method with
				// its corresponding base virtual method.  This is to improve compatibility
				// with non-C# libraries which change the visibility of overrides (#75636)
				//
				int j = 0;
				for (int i = 0; i < Methods.Length; ++i) {
					MethodBase m = Methods [i];
					if (TypeManager.IsOverride (m)) {
						if (candidate_overrides == null)
							candidate_overrides = new ArrayList ();
						candidate_overrides.Add (m);
						m = TypeManager.TryGetBaseDefinition (m);
					}
					if (m != null)
						Methods [j++] = m;
				}
				nmethods = j;
			}

			//
			// Enable message recording, it's used mainly by lambda expressions
			//
			SessionReportPrinter msg_recorder = new SessionReportPrinter ();
			ReportPrinter prev_recorder = ec.Report.SetPrinter (msg_recorder);

			//
			// First we construct the set of applicable methods
			//
			bool is_sorted = true;
			int best_candidate_rate = int.MaxValue;
			for (int i = 0; i < nmethods; i++) {
				Type decl_type = Methods [i].DeclaringType;

				//
				// If we have already found an applicable method
				// we eliminate all base types (Section 14.5.5.1)
				//
				if (applicable_type != null && IsAncestralType (decl_type, applicable_type))
					continue;

				//
				// Check if candidate is applicable (section 14.4.2.1)
				//
				bool params_expanded_form = false;
				int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref Methods [i], ref params_expanded_form);

				if (candidate_rate < best_candidate_rate) {
					best_candidate_rate = candidate_rate;
					best_candidate = Methods [i];
				}
				
				if (params_expanded_form) {
					if (candidate_to_form == null)
						candidate_to_form = new PtrHashtable ();
					MethodBase candidate = Methods [i];
					candidate_to_form [candidate] = candidate;
				}
				
				if (candidate_args != Arguments) {
					if (candidates_expanded == null)
						candidates_expanded = new Hashtable (2);

					candidates_expanded.Add (Methods [i], candidate_args);
					candidate_args = Arguments;
				}

				if (candidate_rate != 0 || has_inaccessible_candidates_only) {
					if (msg_recorder != null)
						msg_recorder.EndSession ();
					continue;
				}

				msg_recorder = null;
				candidates.Add (Methods [i]);

				if (applicable_type == null)
					applicable_type = decl_type;
				else if (applicable_type != decl_type) {
					is_sorted = false;
					if (IsAncestralType (applicable_type, decl_type))
						applicable_type = decl_type;
				}
			}

			ec.Report.SetPrinter (prev_recorder);
			if (msg_recorder != null && !msg_recorder.IsEmpty) {
				if (!may_fail)
					msg_recorder.Merge (prev_recorder);

				return null;
			}
			
			int candidate_top = candidates.Count;

			if (applicable_type == null) {
				//
				// When we found a top level method which does not match and it's 
				// not an extension method. We start extension methods lookup from here
				//
				if (InstanceExpression != null) {
					ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, Name, loc);
					if (ex_method_lookup != null) {
						ex_method_lookup.ExtensionExpression = InstanceExpression;
						ex_method_lookup.SetTypeArguments (ec, type_arguments);
						return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
					}
				}
				
				if (may_fail)
					return null;

				//
				// Okay so we have failed to find exact match so we
				// return error info about the closest match
				//
				if (best_candidate != null) {
					if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
						return null;

					AParametersCollection pd = TypeManager.GetParameterData (best_candidate);
					bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
					if (arg_count == pd.Count || pd.HasParams) {
						if (TypeManager.IsGenericMethodDefinition (best_candidate)) {
							if (type_arguments == null) {
								ec.Report.Error (411, loc,
									"The type arguments for method `{0}' cannot be inferred from " +
									"the usage. Try specifying the type arguments explicitly",
									TypeManager.CSharpSignature (best_candidate));
								return null;
							}

							Type[] g_args = TypeManager.GetGenericArguments (best_candidate);
							if (type_arguments.Count != g_args.Length) {
								ec.Report.SymbolRelatedToPreviousError (best_candidate);
								ec.Report.Error (305, loc, "Using the generic method `{0}' requires `{1}' type argument(s)",
									TypeManager.CSharpSignature (best_candidate),
									g_args.Length.ToString ());
								return null;
							}
						} else {
							if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) {
								Namespace.Error_TypeArgumentsCannotBeUsed (best_candidate, loc);
								return null;
							}
						}

						if (has_inaccessible_candidates_only) {
							if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) {
								// Although a derived class can access protected members of
								// its base class it cannot do so through an instance of the
								// base class (CS1540).  If the qualifier_type is a base of the
								// ec.CurrentType and the lookup succeeds with the latter one,
								// then we are in this situation.
								Error_CannotAccessProtected (ec, loc, best_candidate, queried_type, ec.CurrentType);
							} else {
								ec.Report.SymbolRelatedToPreviousError (best_candidate);
								ErrorIsInaccesible (loc, GetSignatureForError (), ec.Report);
							}
						}

						if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
							return null;

						if (has_inaccessible_candidates_only)
							return null;

						throw new InternalErrorException ("VerifyArgumentsCompat didn't find any problem with rejected candidate " + best_candidate);
					}
				}

				//
				// We failed to find any method with correct argument count
				//
				if (Name == ConstructorInfo.ConstructorName) {
					ec.Report.SymbolRelatedToPreviousError (queried_type);
					ec.Report.Error (1729, loc,
						"The type `{0}' does not contain a constructor that takes `{1}' arguments",
						TypeManager.CSharpName (queried_type), arg_count);
				} else {
					Error_ArgumentCountWrong (ec, arg_count);
				}
                                
				return null;
			}

			if (!is_sorted) {
				//
				// At this point, applicable_type is _one_ of the most derived types
				// in the set of types containing the methods in this MethodGroup.
				// Filter the candidates so that they only contain methods from the
				// most derived types.
				//

				int finalized = 0; // Number of finalized candidates

				do {
					// Invariant: applicable_type is a most derived type
					
					// We'll try to complete Section 14.5.5.1 for 'applicable_type' by 
					// eliminating all it's base types.  At the same time, we'll also move
					// every unrelated type to the end of the array, and pick the next
					// 'applicable_type'.

					Type next_applicable_type = null;
					int j = finalized; // where to put the next finalized candidate
					int k = finalized; // where to put the next undiscarded candidate
					for (int i = finalized; i < candidate_top; ++i) {
						MethodBase candidate = (MethodBase) candidates [i];
						Type decl_type = candidate.DeclaringType;

						if (decl_type == applicable_type) {
							candidates [k++] = candidates [j];
							candidates [j++] = candidates [i];
							continue;
						}

						if (IsAncestralType (decl_type, applicable_type))
							continue;

						if (next_applicable_type != null &&
							IsAncestralType (decl_type, next_applicable_type))
							continue;

						candidates [k++] = candidates [i];

						if (next_applicable_type == null ||
							IsAncestralType (next_applicable_type, decl_type))
							next_applicable_type = decl_type;
					}

					applicable_type = next_applicable_type;
					finalized = j;
					candidate_top = k;
				} while (applicable_type != null);
			}

			//
			// Now we actually find the best method
			//

			best_candidate = (MethodBase) candidates [0];
			method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);

			//
			// TODO: Broken inverse order of candidates logic does not work with optional
			// parameters used for method overrides and I am not going to fix it for SRE
			//
			if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) {
				candidate_args = (Arguments) candidates_expanded [best_candidate];
				arg_count = candidate_args.Count;
			}

			for (int ix = 1; ix < candidate_top; ix++) {
				MethodBase candidate = (MethodBase) candidates [ix];

				if (candidate == best_candidate)
					continue;

				bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);

				if (BetterFunction (ec, candidate_args, arg_count, 
					candidate, cand_params,
					best_candidate, method_params)) {
					best_candidate = candidate;
					method_params = cand_params;
				}
			}
			//
			// Now check that there are no ambiguities i.e the selected method
			// should be better than all the others
			//
			MethodBase ambiguous = null;
			for (int ix = 1; ix < candidate_top; ix++) {
				MethodBase candidate = (MethodBase) candidates [ix];

				if (candidate == best_candidate)
					continue;

				bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
				if (!BetterFunction (ec, candidate_args, arg_count,
					best_candidate, method_params,
					candidate, cand_params)) 
				{
					if (!may_fail)
						ec.Report.SymbolRelatedToPreviousError (candidate);
					ambiguous = candidate;
				}
			}

			if (ambiguous != null) {
				Error_AmbiguousCall (ec, ambiguous);
				return this;
			}

			//
			// If the method is a virtual function, pick an override closer to the LHS type.
			//
			if (!IsBase && best_candidate.IsVirtual) {
				if (TypeManager.IsOverride (best_candidate))
					throw new InternalErrorException (
						"Should not happen.  An 'override' method took part in overload resolution: " + best_candidate);

				if (candidate_overrides != null) {
					Type[] gen_args = null;
					bool gen_override = false;
					if (TypeManager.IsGenericMethod (best_candidate))
						gen_args = TypeManager.GetGenericArguments (best_candidate);

					foreach (MethodBase candidate in candidate_overrides) {
						if (TypeManager.IsGenericMethod (candidate)) {
							if (gen_args == null)
								continue;

							if (gen_args.Length != TypeManager.GetGenericArguments (candidate).Length)
								continue;
						} else {
							if (gen_args != null)
								continue;
						}
						
						if (IsOverride (candidate, best_candidate)) {
							gen_override = true;
							best_candidate = candidate;
						}
					}

					if (gen_override && gen_args != null) {
#if GMCS_SOURCE
						best_candidate = ((MethodInfo) best_candidate).MakeGenericMethod (gen_args);
#endif						
					}
				}
			}

			//
			// And now check if the arguments are all
			// compatible, perform conversions if
			// necessary etc. and return if everything is
			// all right
			//
			if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
				method_params, may_fail, loc))
				return null;

			if (best_candidate == null)
				return null;

			MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
			if (TypeManager.IsGenericMethodDefinition (the_method) &&
			    !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
				return null;

			//
			// Check ObsoleteAttribute on the best method
			//
			ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (the_method);
			if (oa != null && !ec.IsObsolete)
				AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);

			IMethodData data = TypeManager.GetMethod (the_method);
			if (data != null)
				data.SetMemberIsUsed ();

			Arguments = candidate_args;
			return this;
		}