public static bool CheckImplementingMethodConstraints (TypeContainer container, MethodSpec method, MethodSpec baseMethod) { var tparams = method.Constraints; var base_tparams = baseMethod.Constraints; for (int i = 0; i < tparams.Length; ++i) { if (!tparams[i].HasSameConstraintsImplementation (base_tparams[i])) { container.Compiler.Report.SymbolRelatedToPreviousError (method); container.Compiler.Report.SymbolRelatedToPreviousError (baseMethod); // Using container location because the interface can be implemented // by base class container.Compiler.Report.Error (425, container.Location, "The constraints for type parameter `{0}' of method `{1}' must match the constraints for type parameter `{2}' of interface method `{3}'. Consider using an explicit interface implementation instead", tparams[i].GetSignatureForError (), method.GetSignatureForError (), base_tparams[i].GetSignatureForError (), baseMethod.GetSignatureForError ()); return false; } } return true; }
public bool Define (TypeDefinition container, string method_full_name) { PendingImplementation pending = container.PendingImplementations; MethodSpec ambig_iface_method; bool optional = false; if (pending != null) { implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method, ref optional); if (member.InterfaceType != null) { if (implementing == null) { if (member is PropertyBase) { container.Compiler.Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'", method.GetSignatureForError (), member.InterfaceType.GetSignatureForError (), member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.'))); } else { container.Compiler.Report.Error (539, method.Location, "`{0}.{1}' in explicit interface declaration is not a member of interface", member.InterfaceType.GetSignatureForError (), member.ShortName); } return false; } if (implementing.IsAccessor && !method.IsAccessor) { container.Compiler.Report.SymbolRelatedToPreviousError (implementing); container.Compiler.Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor", member.GetSignatureForError (), implementing.GetSignatureForError ()); return false; } } else { if (implementing != null) { if (!method.IsAccessor) { if (implementing.IsAccessor) { container.Compiler.Report.SymbolRelatedToPreviousError (implementing); container.Compiler.Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'", method.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); } } else if (implementing.DeclaringType.IsInterface) { if (!implementing.IsAccessor) { container.Compiler.Report.SymbolRelatedToPreviousError (implementing); container.Compiler.Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation", method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ()); } else { PropertyBase.PropertyMethod pm = method as PropertyBase.PropertyMethod; if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) { container.Compiler.Report.SymbolRelatedToPreviousError (implementing); container.Compiler.Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'", method.GetSignatureForError (), implementing.GetSignatureForError ()); } } } } } } else { ambig_iface_method = null; } // // For implicit implementations, make sure we are public, for // explicit implementations, make sure we are private. // if (implementing != null){ if (member.IsExplicitImpl) { if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) { container.Compiler.Report.SymbolRelatedToPreviousError (implementing); container.Compiler.Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier", method.GetSignatureForError ()); } if (ambig_iface_method != null) { container.Compiler.Report.SymbolRelatedToPreviousError (ambig_iface_method); container.Compiler.Report.SymbolRelatedToPreviousError (implementing); container.Compiler.Report.Warning (473, 2, method.Location, "Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead", method.GetSignatureForError ()); } } else { // // Setting implementin to null inside this block will trigger a more // verbose error reporting for missing interface implementations // if (implementing.DeclaringType.IsInterface) { // // If this is an interface method implementation, // check for public accessibility // if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) { implementing = null; } else if (optional && (container.Interfaces == null || !container.Definition.Interfaces.Contains (implementing.DeclaringType))) { // // We are not implementing interface when base class already implemented it // implementing = null; } } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) { // We may never be private. implementing = null; } else if ((modifiers & Modifiers.OVERRIDE) == 0) { // // We may be protected if we're overriding something. // implementing = null; } } // // Static is not allowed // if ((modifiers & Modifiers.STATIC) != 0){ implementing = null; } } // // If implementing is still valid, set flags // if (implementing != null){ // // When implementing interface methods, set NewSlot // unless, we are overwriting a method. // if ((modifiers & Modifiers.OVERRIDE) == 0 && implementing.DeclaringType.IsInterface) { flags |= MethodAttributes.NewSlot; } flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig; // Set Final unless we're virtual, abstract or already overriding a method. if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0) flags |= MethodAttributes.Final; // // clear the pending implementation flag (requires explicit methods to be defined first) // pending.ImplementMethod (method.MethodName, member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method, ref optional); // // Update indexer accessor name to match implementing abstract accessor // if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor) method_full_name = implementing.MemberDefinition.Name; } full_name = method_full_name; declaring_type = container.Definition; return true; }
/// <summary> /// This function tells whether one of our base classes implements /// the given method (which turns out, it is valid to have an interface /// implementation in a base /// </summary> bool BaseImplements (TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method) { base_method = null; var base_type = container.BaseType; // // Setup filter with no return type to give better error message // about mismatch at return type when the check bellow rejects them // var parameters = mi.Parameters; while (true) { var candidates = MemberCache.FindMembers (base_type, mi.Name, false); if (candidates == null) return false; MethodSpec similar_candidate = null; foreach (var candidate in candidates) { if (candidate.Kind != MemberKind.Method) continue; if (candidate.Arity != mi.Arity) continue; var candidate_param = ((MethodSpec) candidate).Parameters; if (!TypeSpecComparer.Override.IsSame (parameters.Types, candidate_param.Types)) continue; bool modifiers_match = true; for (int i = 0; i < parameters.Count; ++i) { // // First check exact ref/out match // const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; if ((parameters.FixedParameters[i].ModFlags & ref_out) == (candidate_param.FixedParameters[i].ModFlags & ref_out)) continue; modifiers_match = false; // // Different in ref/out only // if ((parameters.FixedParameters[i].ModFlags & candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0) { 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 on the candidate is used for detailed error reporting // because it's very close match to what we are looking for // base_method = (MethodSpec) candidate; if (!candidate.IsPublic) return false; if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, base_method.ReturnType)) return false; if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints (container, base_method, 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) 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 DefineProxy (iface_type, base_method, mi); } return true; }
public bool Define (DeclSpace parent, string method_full_name, Report Report) { TypeContainer container = parent.PartialContainer; PendingImplementation pending = container.PendingImplementations; if (pending != null){ implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this); if (member.InterfaceType != null){ if (implementing == null){ if (member is PropertyBase) { Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'", method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType), member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.'))); } else { Report.Error (539, method.Location, "`{0}.{1}' in explicit interface declaration is not a member of interface", TypeManager.CSharpName (member.InterfaceType), member.ShortName); } return false; } if (implementing.IsAccessor && !(method is AbstractPropertyEventMethod)) { Report.SymbolRelatedToPreviousError (implementing); Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor", member.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); return false; } } else { if (implementing != null) { AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod; if (prop_method == null) { if (implementing.IsAccessor) { Report.SymbolRelatedToPreviousError (implementing); Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'", method.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); } } else if (implementing.DeclaringType.IsInterface) { if (!implementing.IsAccessor) { Report.SymbolRelatedToPreviousError (implementing); Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation", method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ()); } else { PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod; if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) { Report.SymbolRelatedToPreviousError (implementing); Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'", method.GetSignatureForError (), implementing.GetSignatureForError ()); } } } } } } // // For implicit implementations, make sure we are public, for // explicit implementations, make sure we are private. // if (implementing != null){ // // Setting null inside this block will trigger a more // verbose error reporting for missing interface implementations // // The "candidate" function has been flagged already // but it wont get cleared // if (member.IsExplicitImpl){ if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) { Report.SymbolRelatedToPreviousError (implementing); Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier", method.GetSignatureForError ()); } } else { if (implementing.DeclaringType.IsInterface) { // // If this is an interface method implementation, // check for public accessibility // if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) { implementing = null; } } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){ // We may never be private. implementing = null; } else if ((modifiers & Modifiers.OVERRIDE) == 0){ // // We may be protected if we're overriding something. // implementing = null; } } // // Static is not allowed // if ((modifiers & Modifiers.STATIC) != 0){ implementing = null; } } // // If implementing is still valid, set flags // if (implementing != null){ // // When implementing interface methods, set NewSlot // unless, we are overwriting a method. // if (implementing.DeclaringType.IsInterface){ if ((modifiers & Modifiers.OVERRIDE) == 0) flags |= MethodAttributes.NewSlot; } flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig; // Set Final unless we're virtual, abstract or already overriding a method. if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0) flags |= MethodAttributes.Final; // // clear the pending implementation flag (requires explicit methods to be defined first) // parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName, member.InterfaceType, this, member.IsExplicitImpl); // // Update indexer accessor name to match implementing abstract accessor // if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor) method_full_name = implementing.MemberDefinition.Name; } DefineMethodBuilder (container, method_full_name, method.ParameterInfo); if (builder == null) return false; // if (container.CurrentType != null) // declaring_type = container.CurrentType; // else declaring_type = container.Definition; if (implementing != null && member.IsExplicitImpl) { container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ()); } return true; }
void Error_WrongEnumerator (ResolveContext rc, MethodSpec enumerator) { rc.Report.SymbolRelatedToPreviousError (enumerator); rc.Report.Error (202, loc, "foreach statement requires that the return type `{0}' of `{1}' must have a suitable public MoveNext method and public Current property", enumerator.ReturnType.GetSignatureForError (), enumerator.GetSignatureForError ()); }
void Error_AmbiguousCall(ResolveContext ec, MethodSpec ambiguous) { if (CustomErrorHandler != null && CustomErrorHandler.AmbiguousCall (ec, ambiguous)) return; ec.Report.SymbolRelatedToPreviousError (best_candidate); ec.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'", best_candidate.GetSignatureForError (), ambiguous.GetSignatureForError ()); }
protected override Expression DoResolve(ResolveContext ec) { constructor_method = Delegate.GetConstructor (ec.Compiler, ec.CurrentType, type); var invoke_method = Delegate.GetInvokeMethod (ec.Compiler, type); method_group.DelegateType = type; method_group.CustomErrorHandler = this; Arguments arguments = CreateDelegateMethodArguments (invoke_method.Parameters, loc); method_group = method_group.OverloadResolve (ec, ref arguments, false, loc); if (method_group == null) return null; delegate_method = (MethodSpec) method_group; if (TypeManager.IsNullableType (delegate_method.DeclaringType)) { ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type", TypeManager.GetFullNameSignature (delegate_method)); return null; } Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc); ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr; if (emg != null) { delegate_instance_expression = emg.ExtensionExpression; TypeSpec e_type = delegate_instance_expression.Type; if (TypeManager.IsValueType (e_type)) { ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates", delegate_method.GetSignatureForError (), TypeManager.CSharpName (e_type)); } } TypeSpec rt = delegate_method.ReturnType; Expression ret_expr = new TypeExpression (rt, loc); if (!Delegate.IsTypeCovariant (ret_expr, invoke_method.ReturnType)) { Error_ConversionFailed (ec, delegate_method, ret_expr); } if (delegate_method.IsConditionallyExcluded (loc)) { ec.Report.SymbolRelatedToPreviousError (delegate_method); MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator; if (m != null && m.IsPartialDefinition) { ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'", delegate_method.GetSignatureForError ()); } else { ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method)); } } DoResolveInstanceExpression (ec); eclass = ExprClass.Value; return this; }