internal override void AfterAddingTypeMembersChecks( ConversionsBase conversions, BindingDiagnosticBag diagnostics ) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); if ((object)_explicitInterfaceType != null) { var explicitInterfaceSpecifier = this.ExplicitInterfaceSpecifier; RoslynDebug.Assert(explicitInterfaceSpecifier != null); _explicitInterfaceType.CheckAllConstraints( DeclaringCompilation, conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics ); } if (!_explicitInterfaceImplementations.IsEmpty) { // Note: we delayed nullable-related checks that could pull on NonNullTypes EventSymbol explicitlyImplementedEvent = _explicitInterfaceImplementations[0]; TypeSymbol.CheckNullableReferenceTypeMismatchOnImplementingMember( this.ContainingType, this, explicitlyImplementedEvent, isExplicit: true, diagnostics ); } }
protected MethodSymbol?MethodChecks(TypeWithAnnotations returnType, ImmutableArray <ParameterSymbol> parameters, BindingDiagnosticBag diagnostics) { _lazyReturnType = returnType; _lazyParameters = parameters; // set ReturnsVoid flag this.SetReturnsVoid(_lazyReturnType.IsVoidType()); this.CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); var location = locations[0]; // Checks taken from MemberDefiner::defineMethod if (this.Name == WellKnownMemberNames.DestructorName && this.ParameterCount == 0 && this.Arity == 0 && this.ReturnsVoid) { diagnostics.Add(ErrorCode.WRN_FinalizeMethod, location); } ExtensionMethodChecks(diagnostics); if (IsPartial) { if (MethodKind == MethodKind.ExplicitInterfaceImplementation) { diagnostics.Add(ErrorCode.ERR_PartialMethodNotExplicit, location); } if (!ContainingType.IsPartial()) { diagnostics.Add(ErrorCode.ERR_PartialMethodOnlyInPartialClass, location); } } if (!IsPartial) { LazyAsyncMethodChecks(CancellationToken.None); Debug.Assert(state.HasComplete(CompletionPart.FinishAsyncMethodChecks)); } // The runtime will not treat this method as an override or implementation of another // method unless both the signatures and the custom modifiers match. Hence, in the // case of overrides and *explicit* implementations, we need to copy the custom modifiers // that are in the signature of the overridden/implemented method. (From source, we know // that there can only be one such method, so there are no conflicts.) This is // unnecessary for implicit implementations because, if the custom modifiers don't match, // we'll insert a bridge method (an explicit implementation that delegates to the implicit // implementation) with the correct custom modifiers // (see SourceMemberContainerTypeSymbol.SynthesizeInterfaceMemberImplementation). // This value may not be correct, but we need something while we compute this.OverriddenMethod. // May be re-assigned below. Debug.Assert(_lazyReturnType.CustomModifiers.IsEmpty); _lazyRefCustomModifiers = ImmutableArray <CustomModifier> .Empty; MethodSymbol?overriddenOrExplicitlyImplementedMethod = null; // Note: we're checking if the syntax indicates explicit implementation rather, // than if explicitInterfaceType is null because we don't want to look for an // overridden property if this is supposed to be an explicit implementation. if (MethodKind != MethodKind.ExplicitInterfaceImplementation) { Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault); _lazyExplicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty; // If this method is an override, we may need to copy custom modifiers from // the overridden method (so that the runtime will recognize it as an override). // We check for this case here, while we can still modify the parameters and // return type without losing the appearance of immutability. if (this.IsOverride) { // This computation will necessarily be performed with partially incomplete // information. There is no way we can determine the complete signature // (i.e. including custom modifiers) until we have found the method that // this method overrides. To accommodate this, MethodSymbol.OverriddenOrHiddenMembers // is written to allow relaxed matching of custom modifiers for source methods, // on the assumption that they will be updated appropriately. overriddenOrExplicitlyImplementedMethod = this.OverriddenMethod; if ((object)overriddenOrExplicitlyImplementedMethod != null) { CustomModifierUtils.CopyMethodCustomModifiers(overriddenOrExplicitlyImplementedMethod, this, out _lazyReturnType, out _lazyRefCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: true); } } else if (RefKind == RefKind.RefReadOnly) { var modifierType = Binder.GetWellKnownType(DeclaringCompilation, WellKnownType.System_Runtime_InteropServices_InAttribute, diagnostics, ReturnTypeLocation); _lazyRefCustomModifiers = ImmutableArray.Create(CSharpCustomModifier.CreateRequired(modifierType)); } } else if (ExplicitInterfaceType is not null) { //do this last so that it can assume the method symbol is constructed (except for ExplicitInterfaceImplementation) overriddenOrExplicitlyImplementedMethod = FindExplicitlyImplementedMethod(diagnostics); if (overriddenOrExplicitlyImplementedMethod is not null) { Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault); _lazyExplicitInterfaceImplementations = ImmutableArray.Create <MethodSymbol>(overriddenOrExplicitlyImplementedMethod); CustomModifierUtils.CopyMethodCustomModifiers(overriddenOrExplicitlyImplementedMethod, this, out _lazyReturnType, out _lazyRefCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: false); this.FindExplicitlyImplementedMemberVerification(overriddenOrExplicitlyImplementedMethod, diagnostics); TypeSymbol.CheckNullableReferenceTypeMismatchOnImplementingMember(this.ContainingType, this, overriddenOrExplicitlyImplementedMethod, isExplicit: true, diagnostics); } else { Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault); _lazyExplicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty; Debug.Assert(_lazyReturnType.CustomModifiers.IsEmpty); } } return(overriddenOrExplicitlyImplementedMethod); }