internal SynthesizedLocal( MethodSymbol containingMethodOpt, TypeWithAnnotations type, SynthesizedLocalKind kind, SyntaxNode syntaxOpt = null, bool isPinned = false, RefKind refKind = RefKind.None #if DEBUG , [CallerLineNumber] int createdAtLineNumber = 0, [CallerFilePath] string createdAtFilePath = null #endif ) { Debug.Assert(!type.IsVoidType()); Debug.Assert(!kind.IsLongLived() || syntaxOpt != null); Debug.Assert(refKind != RefKind.Out); Debug.Assert(containingMethodOpt is null || containingMethodOpt.DeclaringCompilation is not null); _containingMethodOpt = containingMethodOpt; _type = type; _kind = kind; _syntaxOpt = syntaxOpt; _isPinned = isPinned; _refKind = refKind; #if DEBUG _createdAtLineNumber = createdAtLineNumber; _createdAtFilePath = createdAtFilePath; #endif }
internal ScriptEntryPoint(NamedTypeSymbol containingType, TypeWithAnnotations returnType) : base(containingType) { Debug.Assert(containingType.IsScriptClass); Debug.Assert(returnType.IsVoidType()); _returnType = returnType; }
protected override void MethodChecks(BindingDiagnosticBag diagnostics) { (_lazyReturnType, _lazyParameters) = MakeParametersAndBindReturnType(diagnostics); this.SetReturnsVoid(_lazyReturnType.IsVoidType()); // If we have a conversion/equality/inequality operator in an interface or static class then we already // have reported that fact as an error. No need to cascade the error further. if ( ( this.ContainingType.IsInterfaceType() && ( MethodKind == MethodKind.Conversion || Name == WellKnownMemberNames.EqualityOperatorName || Name == WellKnownMemberNames.InequalityOperatorName ) ) || this.ContainingType.IsStatic ) { return; } // SPEC: All types referenced in an operator declaration must be at least as accessible // SPEC: as the operator itself. CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); CheckValueParameters(diagnostics); CheckOperatorSignatures(diagnostics); }
internal void ComputeReturnType() { if (_lazyReturnType is object) { return; } var diagnostics = BindingDiagnosticBag.GetInstance(_declarationDiagnostics); TypeSyntax returnTypeSyntax = Syntax.ReturnType; TypeWithAnnotations returnType = _binder.BindType(returnTypeSyntax.SkipRef(), diagnostics); var compilation = DeclaringCompilation; // Skip some diagnostics when the local function is not associated with a compilation // (specifically, local functions nested in expressions in the EE). if (compilation is object) { var location = returnTypeSyntax.Location; if (_refKind == RefKind.RefReadOnly) { compilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: false); } if (returnType.Type.ContainsNativeInteger()) { compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: false); } if (compilation.ShouldEmitNullableAttributes(this) && returnType.NeedsNullableAttribute()) { compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: false); // Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already } } // span-like types are returnable in general if (returnType.IsRestrictedType(ignoreSpanLikeTypes: true)) { // The return type of a method, delegate, or function pointer cannot be '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, returnTypeSyntax.Location, returnType.Type); } Debug.Assert(_refKind == RefKind.None || !returnType.IsVoidType() || returnTypeSyntax.HasErrors); lock (_declarationDiagnostics) { if (_lazyReturnType is object) { diagnostics.Free(); return; } _declarationDiagnostics.AddRangeAndFree(diagnostics); Interlocked.CompareExchange(ref _lazyReturnType, new TypeWithAnnotations.Boxed(returnType), null); } }
internal void ComputeReturnType() { if (!_lazyReturnType.IsDefault) { return; } var diagnostics = DiagnosticBag.GetInstance(); TypeSyntax returnTypeSyntax = _syntax.ReturnType; TypeWithAnnotations returnType = _binder.BindType(returnTypeSyntax.SkipRef(), diagnostics); if (this.IsAsync) { if (this.RefKind != RefKind.None) { ReportBadRefToken(returnTypeSyntax, diagnostics); } else if (returnType.Type.IsBadAsyncReturn(this.DeclaringCompilation)) { diagnostics.Add(ErrorCode.ERR_BadAsyncReturn, this.Locations[0]); } } var location = _syntax.ReturnType.Location; if (_refKind == RefKind.RefReadOnly) { DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: false); } if (returnType.NeedsNullableAttribute()) { DeclaringCompilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: false); // Note: we don't need to warn on annotations used without NonNullTypes context for local functions, as this is handled in binding already } // span-like types are returnable in general if (returnType.IsRestrictedType(ignoreSpanLikeTypes: true)) { // Method or delegate cannot return type '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, returnTypeSyntax.Location, returnType.Type); } Debug.Assert(_refKind == RefKind.None || !returnType.IsVoidType() || returnTypeSyntax.HasErrors); lock (_declarationDiagnostics) { if (!_lazyReturnType.IsDefault) { diagnostics.Free(); return; } _declarationDiagnostics.AddRangeAndFree(diagnostics); _lazyReturnType = returnType; } }
internal SubmissionEntryPoint(NamedTypeSymbol containingType, TypeWithAnnotations returnType, TypeSymbol submissionArrayType) : base(containingType) { Debug.Assert(containingType.IsSubmissionClass); Debug.Assert(!returnType.IsVoidType()); _parameters = ImmutableArray.Create(SynthesizedParameterSymbol.Create(this, TypeWithAnnotations.Create(submissionArrayType), 0, RefKind.None, "submissionArray")); _returnType = returnType; }
protected SourceDelegateMethodSymbol( SourceMemberContainerTypeSymbol delegateType, TypeWithAnnotations returnType, DelegateDeclarationSyntax syntax, MethodKind methodKind, DeclarationModifiers declarationModifiers) : base(delegateType, syntax.GetReference(), location: syntax.Identifier.GetLocation(), isIterator: false) { _returnType = returnType; this.MakeFlags(methodKind, declarationModifiers, _returnType.IsVoidType(), isExtensionMethod: false); }
protected override void MethodChecks(DiagnosticBag diagnostics) { // These values may not be final, but we need to have something set here in the // event that we need to find the overridden accessor. _lazyParameters = ComputeParameters(diagnostics); _lazyReturnType = ComputeReturnType(diagnostics); _lazyRefCustomModifiers = ImmutableArray <CustomModifier> .Empty; if (_explicitInterfaceImplementations.Length > 0) { Debug.Assert(_explicitInterfaceImplementations.Length == 1); MethodSymbol implementedMethod = _explicitInterfaceImplementations[0]; CustomModifierUtils.CopyMethodCustomModifiers(implementedMethod, this, out _lazyReturnType, out _lazyRefCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: false); } else if (this.IsOverride) { // This will cause another call to SourceMethodSymbol.LazyMethodChecks, // but that method already handles reentrancy for exactly this case. MethodSymbol overriddenMethod = this.OverriddenMethod; if ((object)overriddenMethod != null) { CustomModifierUtils.CopyMethodCustomModifiers(overriddenMethod, this, out _lazyReturnType, out _lazyRefCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: true); } } else if (!_lazyReturnType.IsVoidType()) { PropertySymbol associatedProperty = _property; var type = associatedProperty.TypeWithAnnotations; _lazyReturnType = _lazyReturnType.WithTypeAndModifiers( CustomModifierUtils.CopyTypeCustomModifiers(type.Type, _lazyReturnType.Type, this.ContainingAssembly), type.CustomModifiers); _lazyRefCustomModifiers = associatedProperty.RefCustomModifiers; } }
protected override void MethodChecks(DiagnosticBag diagnostics) { var binder = this.DeclaringCompilation. GetBinderFactory(syntaxReferenceOpt.SyntaxTree).GetBinder(ReturnTypeSyntax, GetSyntax(), this); SyntaxToken arglistToken; var signatureBinder = binder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks); _lazyParameters = ParameterHelpers.MakeParameters( signatureBinder, this, ParameterListSyntax, out arglistToken, allowRefOrOut: true, allowThis: false, addRefReadOnlyModifier: false, diagnostics: diagnostics); if (arglistToken.Kind() == SyntaxKind.ArgListKeyword) { // This is a parse-time error in the native compiler; it is a semantic analysis error in Roslyn. // error CS1669: __arglist is not valid in this context diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, new SourceLocation(arglistToken)); // Regardless of whether __arglist appears in the source code, we do not mark // the operator method as being a varargs method. } _lazyReturnType = signatureBinder.BindType(ReturnTypeSyntax, diagnostics); // restricted types cannot be returned. // NOTE: Span-like types can be returned (if expression is returnable). if (_lazyReturnType.IsRestrictedType(ignoreSpanLikeTypes: true)) { // Method or delegate cannot return type '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, ReturnTypeSyntax.Location, _lazyReturnType.Type); } if (_lazyReturnType.Type.IsStatic) { // '{0}': static types cannot be used as return types diagnostics.Add(ErrorCode.ERR_ReturnTypeIsStaticClass, ReturnTypeSyntax.Location, _lazyReturnType.Type); } this.SetReturnsVoid(_lazyReturnType.IsVoidType()); // If we have a conversion/equality/inequality operator in an interface or static class then we already // have reported that fact as an error. No need to cascade the error further. if ((this.ContainingType.IsInterfaceType() && (MethodKind == MethodKind.Conversion || Name == WellKnownMemberNames.EqualityOperatorName || Name == WellKnownMemberNames.InequalityOperatorName)) || this.ContainingType.IsStatic) { return; } // SPEC: All types referenced in an operator declaration must be at least as accessible // SPEC: as the operator itself. CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); CheckValueParameters(diagnostics); CheckOperatorSignatures(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); this.CheckFileTypeUsage(_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.CheckNullableReferenceTypeAndScopedMismatchOnImplementingMember(this.ContainingType, this, overriddenOrExplicitlyImplementedMethod, isExplicit: true, diagnostics); } else { Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault); _lazyExplicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty; Debug.Assert(_lazyReturnType.CustomModifiers.IsEmpty); } } return(overriddenOrExplicitlyImplementedMethod); }