+ bool modifiers_match = true;
+ for (int i = 0; i < parameters.Count; ++i) {
+ //
+ // First check exact ref/out match
+ //
+ if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
+ continue;
+
+ modifiers_match = false;
+
+ //
+ // Different in ref/out only
+ //
+ if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) {
+ if (similar_candidate == null) {
+ if (!candidate.IsPublic)
+ break;
+
+ if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, ((MethodSpec) candidate).ReturnType))
+ break;
+
+ // It's used for ref/out ambiguity overload check
+ similar_candidate = (MethodSpec) candidate;
+ }
+
+ continue;
+ }
+
+ similar_candidate = null;
+ break;
+ }
+
+ if (!modifiers_match)
+ continue;
+
+ //
+ // From this point the candidate is used for detailed error reporting
+ // because it's very close match to what we are looking for
+ //
+ var m = (MethodSpec) candidate;
+
+ if (!m.IsPublic) {
+ if (close_match == null)
+ close_match = m;
+
+ continue;
+ }
+
+ if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, m.ReturnType)) {
+ if (close_match == null)
+ close_match = m;
+
+ continue;
+ }
+
+ base_method = m;
+
+ if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints (container, m, mi)) {
+ return true;
+ }
+ }
+
+ if (base_method != null) {
+ if (similar_candidate != null) {
+ Report.SymbolRelatedToPreviousError (similar_candidate);
+ Report.SymbolRelatedToPreviousError (mi);
+ Report.SymbolRelatedToPreviousError (container);
+ Report.Warning (1956, 1, ((MemberCore) base_method.MemberDefinition).Location,
+ "The interface method `{0}' implementation is ambiguous between following methods: `{1}' and `{2}' in type `{3}'",
+ mi.GetSignatureForError (), base_method.GetSignatureForError (), similar_candidate.GetSignatureForError (), container.GetSignatureForError ());
+ }
+
+ break;
+ }
+
+ base_type = candidates[0].DeclaringType.BaseType;
+ if (base_type == null) {
+ base_method = close_match;
+ return false;
+ }
+ }
+
+ if (!base_method.IsVirtual) {
+#if STATIC
+ var base_builder = base_method.GetMetaInfo () as MethodBuilder;
+ if (base_builder != null) {
+ //
+ // We can avoid creating a proxy if base_method can be marked 'final virtual'. This can
+ // be done for all methods from compiled assembly
+ //
+ base_builder.__SetAttributes (base_builder.Attributes | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot);
+ return true;
+ }
+#endif