private TypeWithAnnotations ComputeReturnType(DiagnosticBag diagnostics) { if (this.MethodKind == MethodKind.PropertyGet) { var type = _property.TypeWithAnnotations; if (!ContainingType.IsInterfaceType() && type.Type.IsStatic) { // '{0}': static types cannot be used as return types diagnostics.Add(ErrorCode.ERR_ReturnTypeIsStaticClass, this.locations[0], type.Type); } return(type); } else { var binder = GetBinder(); var type = TypeWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_Void, diagnostics, this.GetSyntax())); if (IsInitOnly) { var isInitOnlyType = Binder.GetWellKnownType(this.DeclaringCompilation, WellKnownType.System_Runtime_CompilerServices_IsExternalInit, diagnostics, this.locations[0]); var modifiers = ImmutableArray.Create <CustomModifier>( CSharpCustomModifier.CreateRequired(isInitOnlyType)); type = type.WithModifiers(modifiers); } return(type); } }
internal virtual ImmutableArray <CustomModifier> SubstituteCustomModifiers( ImmutableArray <CustomModifier> customModifiers ) { if (customModifiers.IsDefaultOrEmpty) { return(customModifiers); } for (int i = 0; i < customModifiers.Length; i++) { NamedTypeSymbol modifier = ((CSharpCustomModifier)customModifiers[i]).ModifierSymbol; var substituted = SubstituteNamedType(modifier); if (!TypeSymbol.Equals(modifier, substituted, TypeCompareKind.ConsiderEverything2)) { var builder = ArrayBuilder <CustomModifier> .GetInstance(customModifiers.Length); builder.AddRange(customModifiers, i); builder.Add( customModifiers[i].IsOptional ? CSharpCustomModifier.CreateOptional(substituted) : CSharpCustomModifier.CreateRequired(substituted) ); for (i++; i < customModifiers.Length; i++) { modifier = ((CSharpCustomModifier)customModifiers[i]).ModifierSymbol; substituted = SubstituteNamedType(modifier); if ( !TypeSymbol.Equals( modifier, substituted, TypeCompareKind.ConsiderEverything2 ) ) { builder.Add( customModifiers[i].IsOptional ? CSharpCustomModifier.CreateOptional(substituted) : CSharpCustomModifier.CreateRequired(substituted) ); } else { builder.Add(customModifiers[i]); } } Debug.Assert(builder.Count == customModifiers.Length); return(builder.ToImmutableAndFree()); } } return(customModifiers); }
internal InvokeMethod( SourceMemberContainerTypeSymbol delegateType, RefKind refKind, TypeWithAnnotations returnType, DelegateDeclarationSyntax syntax, Binder binder, BindingDiagnosticBag diagnostics ) : base( delegateType, returnType, syntax, MethodKind.DelegateInvoke, DeclarationModifiers.Virtual | DeclarationModifiers.Public ) { this._refKind = refKind; SyntaxToken arglistToken; var parameters = ParameterHelpers.MakeParameters( binder, this, syntax.ParameterList, out arglistToken, allowRefOrOut: true, allowThis: false, addRefReadOnlyModifier: true, 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)); } if (_refKind == RefKind.RefReadOnly) { var modifierType = binder.GetWellKnownType( WellKnownType.System_Runtime_InteropServices_InAttribute, diagnostics, syntax.ReturnType ); _refCustomModifiers = ImmutableArray.Create( CSharpCustomModifier.CreateRequired(modifierType) ); } else { _refCustomModifiers = ImmutableArray<CustomModifier>.Empty; } InitializeParameters(parameters); }
IEnumerable <Cci.TypeReferenceWithAttributes> Cci.IGenericParameter.GetConstraints(EmitContext context) { var moduleBeingBuilt = (PEModuleBuilder)context.Module; var seenValueType = false; if (this.HasUnmanagedTypeConstraint) { var typeRef = moduleBeingBuilt.GetSpecialType( SpecialType.System_ValueType, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, diagnostics: context.Diagnostics); var modifier = CSharpCustomModifier.CreateRequired( moduleBeingBuilt.Compilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_UnmanagedType)); // emit "(class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType" pattern as "unmanaged" yield return(new Cci.TypeReferenceWithAttributes(new Cci.ModifiedTypeReference(typeRef, ImmutableArray.Create <Cci.ICustomModifier>(modifier)))); // do not emit another one for Dev11 similarities seenValueType = true; } foreach (var type in this.ConstraintTypesNoUseSiteDiagnostics) { switch (type.SpecialType) { case SpecialType.System_Object: Debug.Assert(!type.NullableAnnotation.IsAnnotated()); break; case SpecialType.System_ValueType: seenValueType = true; break; } var typeRef = moduleBeingBuilt.Translate(type.Type, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, diagnostics: context.Diagnostics); yield return(type.GetTypeRefWithAttributes( moduleBeingBuilt, declaringSymbol: this, typeRef)); } if (this.HasValueTypeConstraint && !seenValueType) { // Add System.ValueType constraint to comply with Dev11 output var typeRef = moduleBeingBuilt.GetSpecialType(SpecialType.System_ValueType, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, diagnostics: context.Diagnostics); yield return(new Cci.TypeReferenceWithAttributes(typeRef)); } }
public InitAccessorSymbol( SynthesizedRecordPropertySymbol property, string paramName, DiagnosticBag diagnostics) { _property = property; Name = SourcePropertyAccessorSymbol.GetAccessorName( paramName, getNotSet: false, // https://github.com/dotnet/roslyn/issues/44684 isWinMdOutput: false); var comp = property.DeclaringCompilation; var type = TypeWithAnnotations.Create(comp.GetSpecialType(SpecialType.System_Void)); var initOnlyType = Binder.GetWellKnownType( comp, WellKnownType.System_Runtime_CompilerServices_IsExternalInit, diagnostics, property.Location); var modifiers = ImmutableArray.Create <CustomModifier>(CSharpCustomModifier.CreateRequired(initOnlyType)); ReturnTypeWithAnnotations = type.WithModifiers(modifiers); }
public static SourceParameterSymbol Create( Binder context, Symbol owner, TypeWithAnnotations parameterType, ParameterSyntax syntax, RefKind refKind, SyntaxToken identifier, int ordinal, bool isParams, bool isExtensionMethodThis, bool addRefReadOnlyModifier, DiagnosticBag declarationDiagnostics) { Debug.Assert(!(owner is LambdaSymbol)); // therefore we don't need to deal with discard parameters var name = identifier.ValueText; var locations = ImmutableArray.Create <Location>(new SourceLocation(identifier)); if (isParams) { // touch the constructor in order to generate proper use-site diagnostics Binder.ReportUseSiteDiagnosticForSynthesizedAttribute(context.Compilation, WellKnownMember.System_ParamArrayAttribute__ctor, declarationDiagnostics, identifier.Parent.GetLocation()); } if (addRefReadOnlyModifier && refKind == RefKind.In) { var modifierType = context.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_InAttribute, declarationDiagnostics, syntax); return(new SourceComplexParameterSymbolWithCustomModifiersPrecedingByRef( owner, ordinal, parameterType, refKind, ImmutableArray.Create(CSharpCustomModifier.CreateRequired(modifierType)), name, locations, syntax.GetReference(), ConstantValue.Unset, isParams, isExtensionMethodThis)); } if (!isParams && !isExtensionMethodThis && (syntax.Default == null) && (syntax.AttributeLists.Count == 0) && !owner.IsPartialMethod()) { return(new SourceSimpleParameterSymbol(owner, parameterType, ordinal, refKind, name, isDiscard: false, locations)); } return(new SourceComplexParameterSymbol( owner, ordinal, parameterType, refKind, name, locations, syntax.GetReference(), ConstantValue.Unset, isParams, isExtensionMethodThis)); }
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); }
private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsBinder, DiagnosticBag diagnostics) { Debug.Assert(this.MethodKind != MethodKind.UserDefinedOperator, "SourceUserDefinedOperatorSymbolBase overrides this"); SyntaxToken arglistToken; // Constraint checking for parameter and return types must be delayed until // the method has been added to the containing type member list since // evaluating the constraints may depend on accessing this method from // the container (comparing this method to others to find overrides for // instance). Constraints are checked in AfterAddingTypeMembersChecks. var signatureBinder = withTypeParamsBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this); _lazyParameters = ParameterHelpers.MakeParameters( signatureBinder, this, syntax.ParameterList, out arglistToken, allowRefOrOut: true, allowThis: true, addRefReadOnlyModifier: IsVirtual || IsAbstract, diagnostics: diagnostics); _lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); RefKind refKind; var returnTypeSyntax = syntax.ReturnType.SkipRef(out refKind); _lazyReturnType = signatureBinder.BindType(returnTypeSyntax, diagnostics); // span-like types are returnable in general if (_lazyReturnType.IsRestrictedType(ignoreSpanLikeTypes: true)) { if (_lazyReturnType.SpecialType == SpecialType.System_TypedReference && (this.ContainingType.SpecialType == SpecialType.System_TypedReference || this.ContainingType.SpecialType == SpecialType.System_ArgIterator)) { // Two special cases: methods in the special types TypedReference and ArgIterator are allowed to return TypedReference } else { // Method or delegate cannot return type '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, syntax.ReturnType.Location, _lazyReturnType); } } var returnsVoid = _lazyReturnType.SpecialType == SpecialType.System_Void; if (this.RefKind != RefKind.None && returnsVoid) { Debug.Assert(returnTypeSyntax.HasErrors); } // set ReturnsVoid flag this.SetReturnsVoid(returnsVoid); var location = this.Locations[0]; this.CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); // Checks taken from MemberDefiner::defineMethod if (this.Name == WellKnownMemberNames.DestructorName && this.ParameterCount == 0 && this.Arity == 0 && this.ReturnsVoid) { diagnostics.Add(ErrorCode.WRN_FinalizeMethod, location); } // errors relevant for extension methods if (IsExtensionMethod) { var parameter0Type = this.Parameters[0].Type; var parameter0RefKind = this.Parameters[0].RefKind; if (!parameter0Type.IsValidExtensionParameterType()) { // Duplicate Dev10 behavior by selecting the parameter type. var parameterSyntax = syntax.ParameterList.Parameters[0]; Debug.Assert(parameterSyntax.Type != null); var loc = parameterSyntax.Type.Location; diagnostics.Add(ErrorCode.ERR_BadTypeforThis, loc, parameter0Type); } else if (parameter0RefKind == RefKind.Ref && !parameter0Type.IsValueType) { diagnostics.Add(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, location, Name); } else if (parameter0RefKind == RefKind.In && parameter0Type.TypeKind != TypeKind.Struct) { diagnostics.Add(ErrorCode.ERR_InExtensionMustBeValueType, location, Name); } else if ((object)ContainingType.ContainingType != null) { diagnostics.Add(ErrorCode.ERR_ExtensionMethodsDecl, location, ContainingType.Name); } else if (!ContainingType.IsScriptClass && !(ContainingType.IsStatic && ContainingType.Arity == 0)) { // Duplicate Dev10 behavior by selecting the containing type identifier. However if there // is no containing type (in the interactive case for instance), select the method identifier. var typeDecl = syntax.Parent as TypeDeclarationSyntax; var identifier = (typeDecl != null) ? typeDecl.Identifier : syntax.Identifier; var loc = identifier.GetLocation(); diagnostics.Add(ErrorCode.ERR_BadExtensionAgg, loc); } else if (!IsStatic) { diagnostics.Add(ErrorCode.ERR_BadExtensionMeth, location); } else { // Verify ExtensionAttribute is available. var attributeConstructor = withTypeParamsBinder.Compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor); if ((object)attributeConstructor == null) { var memberDescriptor = WellKnownMembers.GetDescriptor(WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor); // do not use Binder.ReportUseSiteErrorForAttributeCtor in this case, because we'll need to report a special error id, not a generic use site error. diagnostics.Add( ErrorCode.ERR_ExtensionAttrNotFound, syntax.ParameterList.Parameters[0].Modifiers.FirstOrDefault(SyntaxKind.ThisKeyword).GetLocation(), memberDescriptor.DeclaringTypeMetadataName); } } } if (IsPartial) { // check that there are no out parameters in a partial foreach (var p in this.Parameters) { if (p.RefKind == RefKind.Out) { diagnostics.Add(ErrorCode.ERR_PartialMethodCannotHaveOutParameters, location); break; } } if (MethodKind == MethodKind.ExplicitInterfaceImplementation) { diagnostics.Add(ErrorCode.ERR_PartialMethodNotExplicit, location); } if (!ContainingType.IsPartial() || ContainingType.IsInterface) { 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 SourceNamedTypeSymbol.ImplementInterfaceMember). // This value may not be correct, but we need something while we compute overridden/implemented method. // May be re-assigned below. Debug.Assert(_lazyCustomModifiers == null); _lazyCustomModifiers = CustomModifiersTuple.Empty; // 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 (syntax.ExplicitInterfaceSpecifier == null) { 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. MethodSymbol overriddenMethod = this.OverriddenMethod; if ((object)overriddenMethod != null) { CustomModifierUtils.CopyMethodCustomModifiers(overriddenMethod, this, out _lazyReturnType, out _lazyCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: true); } } else if (_refKind == RefKind.RefReadOnly) { var modifierType = withTypeParamsBinder.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_InAttribute, diagnostics, syntax.ReturnType); _lazyCustomModifiers = CustomModifiersTuple.Create( typeCustomModifiers: ImmutableArray <CustomModifier> .Empty, refCustomModifiers: ImmutableArray.Create(CSharpCustomModifier.CreateRequired(modifierType))); } } else if ((object)_explicitInterfaceType != null) { //do this last so that it can assume the method symbol is constructed (except for ExplicitInterfaceImplementation) MethodSymbol implementedMethod = this.FindExplicitlyImplementedMethod(_explicitInterfaceType, syntax.Identifier.ValueText, syntax.ExplicitInterfaceSpecifier, diagnostics); if ((object)implementedMethod != null) { Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault); _lazyExplicitInterfaceImplementations = ImmutableArray.Create <MethodSymbol>(implementedMethod); CustomModifierUtils.CopyMethodCustomModifiers(implementedMethod, this, out _lazyReturnType, out _lazyCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: false); } else { Debug.Assert(_lazyExplicitInterfaceImplementations.IsDefault); _lazyExplicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty; } } CheckModifiers(_hasAnyBody, location, diagnostics); foreach (var typeParameter in _typeParameters) { if (typeParameter.HasUnmanagedTypeConstraint) { DeclaringCompilation.EnsureIsUnmanagedAttributeExists(diagnostics, typeParameter.GetNonNullSyntaxNode().Location, modifyCompilationForIsUnmanaged: true); } } }
internal ImmutableArray <CustomModifier> SubstituteCustomModifiers(ImmutableArray <CustomModifier> customModifiers) { if (customModifiers.IsDefaultOrEmpty) { return(customModifiers); } for (int i = 0; i < customModifiers.Length; i++) { var modifier = (NamedTypeSymbol)customModifiers[i].Modifier; var substituted = SubstituteNamedType(modifier); if (modifier != substituted) { var builder = ArrayBuilder <CustomModifier> .GetInstance(customModifiers.Length); builder.AddRange(customModifiers, i); builder.Add(customModifiers[i].IsOptional ? CSharpCustomModifier.CreateOptional(substituted) : CSharpCustomModifier.CreateRequired(substituted)); for (i++; i < customModifiers.Length; i++) { modifier = (NamedTypeSymbol)customModifiers[i].Modifier; substituted = SubstituteNamedType(modifier); if (modifier != substituted) { builder.Add(customModifiers[i].IsOptional ? CSharpCustomModifier.CreateOptional(substituted) : CSharpCustomModifier.CreateRequired(substituted)); } else { builder.Add(customModifiers[i]); } } Debug.Assert(builder.Count == customModifiers.Length); return(builder.ToImmutableAndFree()); } } return(customModifiers); }