diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index a76b0e21f90aa..22f1681ce31a0 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6941,4 +6941,25 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The type name only contains lower-cased ascii characters. Such names may become reserved for the language. + + Types and aliases cannot be named 'required'. + + + required members + + + '{0}': cannot remove 'required' from '{1}' when overriding + + + Required member '{0}' cannot be hidden by '{1}'. + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + + Required member '{0}' must be settable. + diff --git a/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs b/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs index 68917838c97bd..aa111512f55b1 100644 --- a/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs +++ b/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs @@ -750,6 +750,7 @@ private static ImmutableSegmentedDictionary GetNonTypeMember bool anyMethodHadExtensionSyntax = false; bool anyMemberHasAttributes = false; bool anyNonTypeMembers = false; + bool anyRequiredMembers = false; var memberNameBuilder = s_memberNameBuilderPool.Allocate(); @@ -769,6 +770,11 @@ private static ImmutableSegmentedDictionary GetNonTypeMember { anyMemberHasAttributes = true; } + + if (!anyRequiredMembers && checkPropertyOrFieldMemberForRequiredModifier(member)) + { + anyRequiredMembers = true; + } } if (anyMethodHadExtensionSyntax) @@ -786,7 +792,24 @@ private static ImmutableSegmentedDictionary GetNonTypeMember declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers; } + if (anyRequiredMembers) + { + declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasRequiredMembers; + } + return ToImmutableAndFree(memberNameBuilder); + + static bool checkPropertyOrFieldMemberForRequiredModifier(Syntax.InternalSyntax.CSharpSyntaxNode member) + { + var modifiers = member switch + { + Syntax.InternalSyntax.FieldDeclarationSyntax fieldDeclaration => fieldDeclaration.Modifiers, + Syntax.InternalSyntax.PropertyDeclarationSyntax propertyDeclaration => propertyDeclaration.Modifiers, + _ => default + }; + + return modifiers.Any((int)SyntaxKind.RequiredKeyword); + } } private static bool CheckMethodMemberForExtensionSyntax(Syntax.InternalSyntax.CSharpSyntaxNode member) diff --git a/src/Compilers/CSharp/Portable/Declarations/SingleTypeDeclaration.cs b/src/Compilers/CSharp/Portable/Declarations/SingleTypeDeclaration.cs index c7ec229bc4ba1..79fb9ad4e4bd5 100644 --- a/src/Compilers/CSharp/Portable/Declarations/SingleTypeDeclaration.cs +++ b/src/Compilers/CSharp/Portable/Declarations/SingleTypeDeclaration.cs @@ -56,6 +56,8 @@ internal enum TypeDeclarationFlags : ushort HasReturnWithExpression = 1 << 8, IsSimpleProgram = 1 << 9, + + HasRequiredMembers = 1 << 10, } internal SingleTypeDeclaration( @@ -189,6 +191,8 @@ public bool IsSimpleProgram } } + public bool HasRequiredMembers => (_flags & TypeDeclarationFlags.HasRequiredMembers) != 0; + protected override ImmutableArray GetNamespaceOrTypeDeclarationChildren() { return StaticCast.From(_children); diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index c6ac42c8d647c..548dcc4ff83fe 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2029,5 +2029,14 @@ internal enum ErrorCode #endregion // Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd) + + // PROTOTYPE(req): Move above the comment and condense before merge + + ERR_RequiredNameDisallowed = 9500, + ERR_OverrideMustHaveRequired = 9501, + ERR_RequiredMemberCannotBeHidden = 9502, + ERR_RequiredMemberCannotBeLessVisibleThanContainingType = 9503, + ERR_ExplicitRequiredMember = 9504, + ERR_RequiredMemberMustBeSettable = 9505, } } diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/SynthesizedStateMachineProperty.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/SynthesizedStateMachineProperty.cs index de2abd9ed0871..8ca68abb3e257 100644 --- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/SynthesizedStateMachineProperty.cs +++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/SynthesizedStateMachineProperty.cs @@ -151,6 +151,8 @@ public override bool IsExtern get { return false; } } + internal override bool IsRequired => false; + internal override ObsoleteAttributeData ObsoleteAttributeData { get { return null; } diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousManager.TypeOrDelegatePublicSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousManager.TypeOrDelegatePublicSymbol.cs index 4e812f1310579..36e8bb11c2d01 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousManager.TypeOrDelegatePublicSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousManager.TypeOrDelegatePublicSymbol.cs @@ -123,6 +123,8 @@ internal sealed override bool HasSpecialName get { return false; } } + internal override bool HasDeclaredRequiredMembers => false; + public sealed override ImmutableArray GetTypeMembers() { return ImmutableArray.Empty; diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.FieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.FieldSymbol.cs index 10010ac113676..da38096f344db 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.FieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.FieldSymbol.cs @@ -150,6 +150,8 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r ImmutableArray.Create( new TypedConstant(manager.System_Diagnostics_DebuggerBrowsableState, TypedConstantKind.Enum, DebuggerBrowsableState.Never)))); } + + internal override bool IsRequired => false; } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertySymbol.cs index d55c65c360a9f..5d5630d1af30d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.PropertySymbol.cs @@ -129,6 +129,8 @@ public override bool IsAbstract get { return false; } } + internal override bool IsRequired => false; + internal sealed override ObsoleteAttributeData ObsoleteAttributeData { get { return null; } diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs index 328d7f9663bcb..41ec114a2b5e5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs @@ -189,6 +189,8 @@ internal void AdjustLocation(Location location) } } + internal override bool HasDeclaredRequiredMembers => false; + public override ImmutableArray GetMembers() { return _members; diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index 3f4d5439a0f92..9be3a87f906a3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -1377,6 +1377,9 @@ private static bool SatisfiesConstructorConstraint(TypeSymbol typeArgument) private static bool HasPublicParameterlessConstructor(NamedTypeSymbol type, bool synthesizedIfMissing) { Debug.Assert(type.TypeKind is TypeKind.Class or TypeKind.Struct); + + // PROTOTYPE(req): Adjust for required members + foreach (var constructor in type.InstanceConstructors) { if (constructor.ParameterCount == 0) diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorPropertySymbol.cs index 09256e0b3b6f8..536658ed92722 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorPropertySymbol.cs @@ -77,6 +77,8 @@ public ErrorPropertySymbol(Symbol containingSymbol, TypeSymbol type, string name public override bool IsExtern { get { return false; } } + internal override bool IsRequired => false; + internal sealed override ObsoleteAttributeData ObsoleteAttributeData { get { return null; } } public override ImmutableArray Parameters { get { return ImmutableArray.Empty; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs index fdb77ade632e6..286394b84209e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs @@ -130,6 +130,8 @@ public override IEnumerable MemberNames } } + internal sealed override bool HasDeclaredRequiredMembers => false; + /// /// Get all the members of this symbol. /// diff --git a/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs index 52953a754b53c..3d5fdb7b3d910 100644 --- a/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/FieldSymbol.cs @@ -325,6 +325,11 @@ internal virtual FieldSymbol AsMember(NamedTypeSymbol newOwner) return newOwner.IsDefinition ? this : new SubstitutedFieldSymbol(newOwner as SubstitutedNamedTypeSymbol, this); } + /// + /// Returns true if this field is required to be set in an object initializer on object creation. + /// + internal abstract bool IsRequired { get; } + #region Use-Site Diagnostics internal override UseSiteInfo GetUseSiteInfo() diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs index 6895447a75757..f5d35611fd6f4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEFieldSymbol.cs @@ -587,5 +587,8 @@ internal override ObsoleteAttributeData ObsoleteAttributeData { get { return null; } } + + // PROTOTYPE(req): Implement + internal override bool IsRequired => false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index df6df4a607427..dc8229e580697 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs @@ -824,6 +824,9 @@ private static ICollection CreateReadOnlyMemberNames(HashSet nam } } + // PROTOTYPE(req): Implement + internal override bool HasDeclaredRequiredMembers => false; + public override ImmutableArray GetMembers() { EnsureAllMembersAreLoaded(); diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs index 4ea1a910336f1..8e24f9904c191 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs @@ -462,6 +462,15 @@ public override bool IsStatic } } + internal override bool IsRequired + { + get + { + // PROTOTYPE(req): Implement + return false; + } + } + public override ImmutableArray Parameters { get { return _parameters; } diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index f3b25e788f511..7cb9d7c0f7086 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs @@ -494,6 +494,11 @@ internal abstract bool MangleName /// public abstract IEnumerable MemberNames { get; } + /// + /// True if this type declares any required members. It does not recursively check up the tree for _all_ required members. + /// + internal abstract bool HasDeclaredRequiredMembers { get; } + /// /// Get all the members of this symbol. /// diff --git a/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs index 68be107541d06..9487c7a2ab270 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs @@ -46,6 +46,8 @@ internal NativeIntegerTypeSymbol(NamedTypeSymbol underlyingType) : base(underlyi public override IEnumerable MemberNames => GetMembers().Select(m => m.Name); + internal override bool HasDeclaredRequiredMembers => false; + /// /// Certain members from the underlying types are not exposed from the native integer types: /// constructors other than the default parameterless constructor are not supported; diff --git a/src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs index 72d99b8ffed28..04078ac60e638 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs @@ -182,6 +182,11 @@ public bool IsWriteOnly } } + /// + /// Returns true if this property is required to be set in an object initializer on object creation. + /// + internal abstract bool IsRequired { get; } + /// /// True if the property itself is excluded from code coverage instrumentation. /// True for source properties marked with . diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs index 4bd11b5db2f26..13fb6fd8f15eb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs @@ -120,6 +120,8 @@ public override IEnumerable MemberNames } } + internal override bool HasDeclaredRequiredMembers => _underlyingType.HasDeclaredRequiredMembers; + public override ImmutableArray GetMembers() { return this.RetargetingTranslator.Retarget(_underlyingType.GetMembers()); diff --git a/src/Compilers/CSharp/Portable/Symbols/SignatureOnlyPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SignatureOnlyPropertySymbol.cs index fee6bf4bcadeb..0c2297b9ce522 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SignatureOnlyPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SignatureOnlyPropertySymbol.cs @@ -85,6 +85,8 @@ public SignatureOnlyPropertySymbol( public override bool IsExtern { get { throw ExceptionUtilities.Unreachable; } } + internal override bool IsRequired => throw ExceptionUtilities.Unreachable; + internal override ObsoleteAttributeData ObsoleteAttributeData { get { throw ExceptionUtilities.Unreachable; } } public override AssemblySymbol ContainingAssembly { get { throw ExceptionUtilities.Unreachable; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs index e9d21aff2101a..da07913a6e0dd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs @@ -204,7 +204,14 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu MarshalAsAttributeDecoder.Decode(ref arguments, AttributeTargets.Field, MessageProvider.Instance); } else if (ReportExplicitUseOfReservedAttributes(in arguments, - ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute)) + ReservedAttributes.DynamicAttribute + | ReservedAttributes.IsReadOnlyAttribute + | ReservedAttributes.IsUnmanagedAttribute + | ReservedAttributes.IsByRefLikeAttribute + | ReservedAttributes.TupleElementNamesAttribute + | ReservedAttributes.NullableAttribute + | ReservedAttributes.NativeIntegerAttribute + | ReservedAttributes.RequiredMemberAttribute)) { } else if (attribute.IsTargetAttribute(this, AttributeDescription.DateTimeConstantAttribute)) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs index f28cdf1356928..1d70c5a1b6aa2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs @@ -81,12 +81,13 @@ internal static DeclarationModifiers CheckModifiers( modifierErrors = true; } - if ((result & DeclarationModifiers.PrivateProtected) != 0) - { - modifierErrors |= !Binder.CheckFeatureAvailability(errorLocation.SourceTree, MessageID.IDS_FeaturePrivateProtected, diagnostics, errorLocation); - } + modifierErrors |= checkFeature(DeclarationModifiers.PrivateProtected, MessageID.IDS_FeaturePrivateProtected) + | checkFeature(DeclarationModifiers.Required, MessageID.IDS_FeatureRequiredMembers); return result; + + bool checkFeature(DeclarationModifiers modifier, MessageID featureID) + => ((result & modifier) != 0) && !Binder.CheckFeatureAvailability(errorLocation.SourceTree, featureID, diagnostics, errorLocation); } private static void ReportPartialError(Location errorLocation, BindingDiagnosticBag diagnostics, SyntaxTokenList? modifierTokens) @@ -281,6 +282,8 @@ internal static string ConvertSingleModifierToSyntaxText(DeclarationModifiers mo return SyntaxFacts.GetText(SyntaxKind.AsyncKeyword); case DeclarationModifiers.Ref: return SyntaxFacts.GetText(SyntaxKind.RefKeyword); + case DeclarationModifiers.Required: + return SyntaxFacts.GetText(SyntaxKind.RequiredKeyword); default: throw ExceptionUtilities.UnexpectedValue(modifier); } @@ -328,6 +331,8 @@ private static DeclarationModifiers ToDeclarationModifier(SyntaxKind kind) return DeclarationModifiers.Volatile; case SyntaxKind.RefKeyword: return DeclarationModifiers.Ref; + case SyntaxKind.RequiredKeyword: + return DeclarationModifiers.Required; default: throw ExceptionUtilities.UnexpectedValue(kind); } @@ -417,6 +422,21 @@ internal static CSDiagnosticInfo CheckAccessibility(DeclarationModifiers modifie } } + if ((modifiers & DeclarationModifiers.Required) != 0) + { + switch (symbol) + { + case FieldSymbol or PropertySymbol when symbol.DeclaredAccessibility < symbol.ContainingType.DeclaredAccessibility: + case PropertySymbol { SetMethod.DeclaredAccessibility: var accessibility } when accessibility < symbol.ContainingType.DeclaredAccessibility: + // Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + return new CSDiagnosticInfo(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, symbol, symbol.ContainingType); + case PropertySymbol { SetMethod: null }: + case FieldSymbol when (modifiers & DeclarationModifiers.ReadOnly) != 0: + // Required member '{0}' must be settable. + return new CSDiagnosticInfo(ErrorCode.ERR_RequiredMemberMustBeSettable, symbol); + } + } + return null; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs index 95c8b305768ac..e0ee0699fd16d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs @@ -10,6 +10,9 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { + // PROTOTYPE(req): Add obsolete marker to constructors if required members and Obsolete hasn't already been emitted + // PROTOTYPE(req): Add poison type marker to constructors if required members and Obsolete hasn't already been emitted, + // pending framework design review internal sealed class SourceConstructorSymbol : SourceConstructorSymbolBase { private readonly bool _isExpressionBodied; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceFieldSymbol.cs index 08ab93bd28469..27f03f3938c9f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceFieldSymbol.cs @@ -154,6 +154,8 @@ internal sealed override bool HasRuntimeSpecialName return this.Name == WellKnownMemberNames.EnumBackingFieldName; } } + + internal override bool IsRequired => (Modifiers & DeclarationModifiers.Required) != 0; } internal abstract class SourceFieldSymbolWithSyntaxReference : SourceFieldSymbol diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index bf05a2b68cf19..94a6a797825de 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -29,7 +29,7 @@ private struct Flags { // We current pack everything into one 32-bit int; layout is given below. // - // | |vvv|zzzz|f|d|yy|wwwwww| + // | |ss|vvv|zzzz|f|d|yy|wwwwww| // // w = special type. 6 bits. // y = IsManagedType. 2 bits. @@ -37,6 +37,7 @@ private struct Flags // f = FlattenedMembersIsSorted. 1 bit. // z = TypeKind. 4 bits. // v = NullableContext. 3 bits. + // s = DeclaredRequiredMembers. 2 bits private int _flags; private const int SpecialTypeOffset = 0; @@ -57,6 +58,9 @@ private struct Flags private const int NullableContextOffset = TypeKindOffset + TypeKindSize; private const int NullableContextSize = 3; + private const int HasDeclaredRequiredMembersOffset = NullableContextOffset + NullableContextSize; + private const int HasDeclaredRequiredMembersSize = 2; + private const int SpecialTypeMask = (1 << SpecialTypeSize) - 1; private const int ManagedKindMask = (1 << ManagedKindSize) - 1; private const int TypeKindMask = (1 << TypeKindSize) - 1; @@ -65,6 +69,8 @@ private struct Flags private const int FieldDefinitionsNotedBit = 1 << FieldDefinitionsNotedOffset; private const int FlattenedMembersIsSortedBit = 1 << FlattenedMembersIsSortedOffset; + private const int HasDeclaredMembersBit = (1 << HasDeclaredRequiredMembersOffset); + private const int HasDeclaredMembersBitSet = (1 << (HasDeclaredRequiredMembersOffset + 1)); public SpecialType SpecialType { @@ -140,6 +146,25 @@ public bool SetNullableContext(byte? value) { return ThreadSafeFlagOperations.Set(ref _flags, (((int)value.ToNullableContextFlags() & NullableContextMask) << NullableContextOffset)); } + + public bool TryGetHasDeclaredRequiredMembers(out bool value) + { + if ((_flags & (HasDeclaredMembersBitSet)) != 0) + { + value = (_flags & HasDeclaredMembersBit) != 0; + return true; + } + else + { + value = false; + return false; + } + } + + public bool SetHasDeclaredRequiredMembers(bool value) + { + return ThreadSafeFlagOperations.Set(ref _flags, HasDeclaredMembersBitSet | (value ? HasDeclaredMembersBit : 0)); + } } private static readonly ObjectPool> s_duplicateRecordMemberSignatureDictionary = @@ -449,14 +474,26 @@ internal static void ReportReservedTypeName(string? name, CSharpCompilation comp return; } - if (name == SyntaxFacts.GetText(SyntaxKind.RecordKeyword) && compilation.LanguageVersion >= MessageID.IDS_FeatureRecords.RequiredVersion()) + if (reportIfContextual(SyntaxKind.RecordKeyword, MessageID.IDS_FeatureRecords, ErrorCode.WRN_RecordNamedDisallowed) + || reportIfContextual(SyntaxKind.RequiredKeyword, MessageID.IDS_FeatureRequiredMembers, ErrorCode.ERR_RequiredNameDisallowed)) { - diagnostics.Add(ErrorCode.WRN_RecordNamedDisallowed, location); + return; } else if (IsReservedTypeName(name)) { diagnostics.Add(ErrorCode.WRN_LowerCaseTypeName, location, name); } + + bool reportIfContextual(SyntaxKind contextualKind, MessageID featureId, ErrorCode error) + { + if (name == SyntaxFacts.GetText(contextualKind) && compilation.LanguageVersion >= featureId.RequiredVersion()) + { + diagnostics.Add(error, location); + return true; + } + + return false; + } } #endregion @@ -1289,6 +1326,21 @@ private void CheckMemberNameDistinctFromType(Symbol member, BindingDiagnosticBag } } + internal override bool HasDeclaredRequiredMembers + { + get + { + if (_flags.TryGetHasDeclaredRequiredMembers(out bool hasDeclaredMembers)) + { + return hasDeclaredMembers; + } + + hasDeclaredMembers = declaration.Declarations.Any(static decl => decl.HasRequiredMembers); + _flags.SetHasDeclaredRequiredMembers(hasDeclaredMembers); + return hasDeclaredMembers; + } + } + internal override ImmutableArray GetMembersUnordered() { var result = _lazyMembersFlattened; @@ -1607,6 +1659,7 @@ protected void AfterMembersChecks(BindingDiagnosticBag diagnostics) CheckSequentialOnPartialType(diagnostics); CheckForProtectedInStaticClass(diagnostics); CheckForUnmatchedOperators(diagnostics); + CheckForRequiredMemberAttribute(diagnostics); var location = Locations[0]; var compilation = DeclaringCompilation; @@ -2340,6 +2393,15 @@ private void CheckForEqualityAndGetHashCode(BindingDiagnosticBag diagnostics) } } + private void CheckForRequiredMemberAttribute(BindingDiagnosticBag diagnostics) + { + if (HasDeclaredRequiredMembers) + { + // Ensure that an error is reported if the required constructor isn't present. + _ = Binder.GetWellKnownTypeMember(DeclaringCompilation, WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor, diagnostics, Locations[0]); + } + } + private bool TypeOverridesObjectMethod(string name) { foreach (var method in this.GetMembers(name).OfType()) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs index 0911c864ce008..5c14d9644ef29 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs @@ -712,6 +712,12 @@ private void CheckNewModifier(Symbol symbol, bool isNew, BindingDiagnosticBag di AddHidingAbstractDiagnostic(symbol, symbolLocation, hiddenMember, diagnostics, ref unused); + if (hiddenMember.IsRequired()) + { + // Required member '{0}' cannot be hidden by '{1}'. + diagnostics.Add(ErrorCode.ERR_RequiredMemberCannotBeHidden, symbolLocation, hiddenMember, symbol); + } + return; } } @@ -900,6 +906,11 @@ void checkSingleOverriddenMember(Symbol overridingMember, Symbol overriddenMembe // it is ok to override with no tuple names, for compatibility with C# 6, but otherwise names should match diagnostics.Add(ErrorCode.ERR_CantChangeTupleNamesOnOverride, overridingMemberLocation, overridingMember, overriddenMember); } + else if (overriddenMember is PropertySymbol { IsRequired: true } && overridingMember is PropertySymbol { IsRequired: false }) + { + // '{0}': cannot remove 'required' from '{1}' when overriding + diagnostics.Add(ErrorCode.ERR_OverrideMustHaveRequired, overridingMemberLocation, overridingMember, overriddenMember); + } else { // As in dev11, we don't compare obsoleteness to the immediately-overridden member, @@ -1410,6 +1421,13 @@ private static void CheckNonOverrideMember( diagnosticAdded = true; } + if (hiddenMember.IsRequired()) + { + // Required member '{0}' cannot be hidden by '{1}'. + diagnostics.Add(ErrorCode.ERR_RequiredMemberCannotBeHidden, hidingMemberLocation, hiddenMember, hidingMember); + diagnosticAdded = true; + } + if (diagnosticAdded) { break; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index b2b6cdf5584d1..380e2c0c4c317 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -114,6 +114,14 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDecimalConstantAttribute(value.DecimalValue)); } } + + // Synthesize RequiredMemberAttribute if this field is required + if (IsRequired) + { + AddSynthesizedAttribute( + ref attributes, + this.DeclaringCompilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor)); + } } public override Symbol AssociatedSymbol @@ -148,7 +156,8 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp DeclarationModifiers.Volatile | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | - DeclarationModifiers.Abstract; // filtered out later + DeclarationModifiers.Abstract | + DeclarationModifiers.Required; // Some of these are filtered out later, when illegal, for better error messages. var errorLocation = new SourceLocation(firstIdentifier); DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers( @@ -186,7 +195,14 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.VolatileKeyword)); } - result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile); + if ((result & DeclarationModifiers.Required) != 0) + { + // PROTOTYPE(req): capture the allowed modifier combinations in the specification + // The modifier 'required' is not valid for this item + diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword)); + } + + result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile | DeclarationModifiers.Required); Debug.Assert((result & ~(DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.New)) == 0); } @@ -216,10 +232,24 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.UnsafeKeyword)); } + if ((result & DeclarationModifiers.Required) != 0) + { + // The modifier 'required' is not valid for this item + diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword)); + result &= ~DeclarationModifiers.Required; + } + result |= DeclarationModifiers.Static; // "constants are considered static members" } else { + if ((result & DeclarationModifiers.Static) != 0 && (result & DeclarationModifiers.Required) != 0) + { + // The modifier 'required' is not valid for this item + diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword)); + result &= ~DeclarationModifiers.Required; + } + // NOTE: always cascading on a const, so suppress. // NOTE: we're being a bit sneaky here - we're using the containingType rather than this symbol // to determine whether or not unsafe is allowed. Since this symbol and the containing type are diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index cacbf6cb60e00..938d9c6dc393c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs @@ -1110,7 +1110,16 @@ internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib diagnostics.Add(ErrorCode.ERR_CantUseRequiredAttribute, arguments.AttributeSyntaxOpt.Name.Location); } else if (ReportExplicitUseOfReservedAttributes(in arguments, - ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NullableContextAttribute | ReservedAttributes.NativeIntegerAttribute | ReservedAttributes.CaseSensitiveExtensionAttribute)) + ReservedAttributes.DynamicAttribute + | ReservedAttributes.IsReadOnlyAttribute + | ReservedAttributes.IsUnmanagedAttribute + | ReservedAttributes.IsByRefLikeAttribute + | ReservedAttributes.TupleElementNamesAttribute + | ReservedAttributes.NullableAttribute + | ReservedAttributes.NullableContextAttribute + | ReservedAttributes.NativeIntegerAttribute + | ReservedAttributes.CaseSensitiveExtensionAttribute + | ReservedAttributes.RequiredMemberAttribute)) { } else if (attribute.IsTargetAttribute(this, AttributeDescription.SecurityCriticalAttribute) @@ -1583,6 +1592,13 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r AddSynthesizedAttribute(ref attributes, this.DeclaringCompilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor)); } + + if (HasDeclaredRequiredMembers) + { + AddSynthesizedAttribute( + ref attributes, + compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor)); + } } #endregion diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index f71c881683cec..1cda7689fda72 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -292,6 +292,11 @@ private static DeclarationModifiers MakeModifiers( if (!isInterface) { allowedModifiers |= DeclarationModifiers.Override; + + if (!isIndexer) + { + allowedModifiers |= DeclarationModifiers.Required; + } } else { @@ -350,6 +355,13 @@ private static DeclarationModifiers MakeModifiers( mods |= DeclarationModifiers.Indexer; } + if ((mods & DeclarationModifiers.Static) != 0 && (mods & DeclarationModifiers.Required) != 0) + { + // The modifier 'required' is not valid for this item + diagnostics.Add(ErrorCode.ERR_BadMemberFlag, location, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword)); + mods &= ~DeclarationModifiers.Required; + } + return mods; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs index 17df109569781..0d8dba89b0121 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs @@ -89,6 +89,7 @@ protected SourcePropertySymbolBase( { Debug.Assert(!isExpressionBodied || !isAutoProperty); Debug.Assert(!isExpressionBodied || !hasInitializer); + Debug.Assert((modifiers & DeclarationModifiers.Required) == 0 || this is SourcePropertySymbol); _syntaxRef = syntax.GetReference(); Location = location; @@ -518,6 +519,8 @@ public override bool IsVirtual get { return (_modifiers & DeclarationModifiers.Virtual) != 0; } } + internal sealed override bool IsRequired => (_modifiers & DeclarationModifiers.Required) != 0; + internal bool IsNew { get { return (_modifiers & DeclarationModifiers.New) != 0; } @@ -1154,6 +1157,13 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r { AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this)); } + + if (IsRequired) + { + AddSynthesizedAttribute( + ref attributes, + compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor)); + } } internal sealed override bool IsDirectlyExcludedFromCodeCoverage => @@ -1267,7 +1277,14 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location); } else if (ReportExplicitUseOfReservedAttributes(in arguments, - ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute)) + ReservedAttributes.DynamicAttribute + | ReservedAttributes.IsReadOnlyAttribute + | ReservedAttributes.IsUnmanagedAttribute + | ReservedAttributes.IsByRefLikeAttribute + | ReservedAttributes.TupleElementNamesAttribute + | ReservedAttributes.NullableAttribute + | ReservedAttributes.NativeIntegerAttribute + | ReservedAttributes.RequiredMemberAttribute)) { } else if (attribute.IsTargetAttribute(this, AttributeDescription.DisallowNullAttribute)) diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs index d3a312282f8c0..5f62fd41389e3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs @@ -204,6 +204,8 @@ public sealed override ImmutableArray GetTypeMembers(string nam return OriginalDefinition.GetTypeMembers(name, arity).SelectAsArray((t, self) => t.AsMember(self), this); } + internal sealed override bool HasDeclaredRequiredMembers => OriginalDefinition.HasDeclaredRequiredMembers; + public sealed override ImmutableArray GetMembers() { var builder = ArrayBuilder.GetInstance(); diff --git a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs index 14d0714f477eb..ea8b6e11a96e2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs @@ -1367,6 +1367,7 @@ internal enum ReservedAttributes NullablePublicOnlyAttribute = 1 << 8, NativeIntegerAttribute = 1 << 9, CaseSensitiveExtensionAttribute = 1 << 10, + RequiredMemberAttribute = 1 << 11, } internal bool ReportExplicitUseOfReservedAttributes(in DecodeWellKnownAttributeArguments arguments, ReservedAttributes reserved) @@ -1421,6 +1422,12 @@ internal bool ReportExplicitUseOfReservedAttributes(in DecodeWellKnownAttributeA // ExtensionAttribute should not be set explicitly. diagnostics.Add(ErrorCode.ERR_ExplicitExtension, arguments.AttributeSyntaxOpt.Location); } + else if ((reserved & ReservedAttributes.RequiredMemberAttribute) != 0 && + attribute.IsTargetAttribute(this, AttributeDescription.RequiredMemberAttribute)) + { + // Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + diagnostics.Add(ErrorCode.ERR_ExplicitRequiredMember, arguments.AttributeSyntaxOpt.Location); + } else { return false; diff --git a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs index 7a27991ad8521..2fa9cce9e30d4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs @@ -839,5 +839,7 @@ internal static bool HasAsyncMethodBuilderAttribute(this Symbol symbol, [NotNull builderArgument = null; return false; } + + internal static bool IsRequired(this Symbol symbol) => symbol is FieldSymbol { IsRequired: true } or PropertySymbol { IsRequired: true }; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs index 6001d8b361c51..156c5ea333769 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs @@ -151,5 +151,7 @@ private void CheckForFieldTargetedAttribute(BindingDiagnosticBag diagnostics) } } } + + internal override bool IsRequired => false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs index e55fc29a04353..96dcf312f9f03 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs @@ -132,6 +132,8 @@ internal override ImmutableArray TypeArgumentsWithAnnotatio internal sealed override bool IsInterpolatedStringHandlerType => false; + internal sealed override bool HasDeclaredRequiredMembers => false; + public override ImmutableArray GetMembers() { Symbol constructor = this.Constructor; diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs index 91fdaa6613923..a03039d83a6ca 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs @@ -67,6 +67,8 @@ public SynthesizedEmbeddedAttributeSymbolBase( public override IEnumerable MemberNames => Constructors.Select(m => m.Name); + internal override bool HasDeclaredRequiredMembers => false; + public override Accessibility DeclaredAccessibility => Accessibility.Internal; public override TypeKind TypeKind => TypeKind.Class; diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldSymbolBase.cs index 73a6dacbcf7ce..23b8a7b28a61c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedFieldSymbolBase.cs @@ -192,5 +192,7 @@ public override bool IsImplicitlyDeclared { get { return true; } } + + internal override bool IsRequired => false; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedFieldSymbol.cs index d623fd5268c5e..166c0264211ce 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedFieldSymbol.cs @@ -204,5 +204,7 @@ public override bool IsStatic return _underlyingField.IsStatic; } } + + internal sealed override bool IsRequired => _underlyingField.IsRequired; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedPropertySymbol.cs index e0ee3f5cdbbb8..e9f62600a2a8a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedPropertySymbol.cs @@ -161,6 +161,8 @@ public override bool IsExtern } } + internal sealed override bool IsRequired => _underlyingProperty.IsRequired; + internal override ObsoleteAttributeData ObsoleteAttributeData { get diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 0c143f283af8f..a19f085033ea8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -432,6 +432,11 @@ Přístupové objekty {0} a {1} by měly být buď oba jenom pro inicializaci, nebo ani jeden. + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Daný výraz nelze použít v příkazu fixed. @@ -977,6 +982,11 @@ Metoda {0} určuje omezení default pro parametr typu {1}, ale odpovídající parametr typu {2} přepsané nebo explicitně implementované metody {3} není omezený na typ odkazu nebo hodnoty. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Metoda {0} určuje omezení class pro parametr typu {1}, ale odpovídající parametr typu {2} přepsané nebo explicitně implementované metody {3} není odkazový typ. @@ -1087,6 +1097,26 @@ Relační vzory se nedají použít pro hodnotu Není číslo s plovoucí desetinnou čárkou. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' {0}: Cílový modul runtime nepodporuje v přepisech kovariantní typy. Typ musí být {2}, aby odpovídal přepsanému členu {1}. @@ -1382,6 +1412,11 @@ struktury záznamů 'record structs' is not localizable. + + required members + required members + + sealed ToString in record zapečetěný ToString v záznamu diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 20f5cf9246ee6..fefcc9f658271 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -432,6 +432,11 @@ "init-only" muss entweder für beide oder für keine der Zugriffsmethoden "{0}" und "{1}" festgelegt sein. + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Der angegebene Ausdruck kann nicht in einer fixed-Anweisung verwendet werden. @@ -977,6 +982,11 @@ Die Methode "{0}" gibt eine default-Einschränkung für den Typparameter "{1}" an, aber der zugehörige Typparameter "{2}" der überschriebenen oder explizit implementierten Methode "{3}" ist auf einen Verweistyp oder einen Werttyp beschränkt. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Die Methode "{0}" gibt eine class-Einschränkung für den Typparameter "{1}" an, aber der zugehörige Typparameter "{2}" der außer Kraft gesetzten oder explizit implementierten Methode "{3}" ist kein Verweistyp. @@ -1087,6 +1097,26 @@ Relationale Muster dürfen nicht für Gleitkomma-NaNs verwendet werden. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' {0}: Die Zielruntime unterstützt keine covarianten Typen in Überschreibungen. Der Typ muss "{2}" sein, um dem überschriebenen Member "{1}" zu entsprechen. @@ -1382,6 +1412,11 @@ Datensatzstrukturen 'record structs' is not localizable. + + required members + required members + + sealed ToString in record versiegelte "ToString" im Datensatz diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index e777231f2d8c5..dd5d8f16dd59d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -432,6 +432,11 @@ Los descriptores de acceso "{0}" y "{1}" deben ser los dos solo de inicialización o ninguno de ellos + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement La expresión proporcionada no se puede utilizar en una instrucción "fixed" @@ -977,6 +982,11 @@ El método "{0}" especifica una restricción "default" para el parámetro de tipo "{1}", pero el parámetro de tipo "{2}" correspondiente del método "{3}" invalidado o implementado explícitamente se restringe a un tipo de referencia o a un tipo de valor. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. El método "{0}" especifica una restricción "class" para el parámetro de tipo "{1}", pero el parámetro de tipo correspondiente "{2}" de los métodos invalidados o implementados explícitamente "{3}" no es un tipo de referencia. @@ -1087,6 +1097,26 @@ No se pueden usar patrones relacionales para un valor NaN de punto flotante. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' "{0}": el entorno de ejecución de destino no admite los tipos de covariante en las invalidaciones. El tipo debe ser "{2}" para que coincida con el miembro "{1}" invalidado. @@ -1382,6 +1412,11 @@ registros 'record structs' is not localizable. + + required members + required members + + sealed ToString in record ToString sellado en el registro diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index a1ec5ce86a71e..60d4172ca9027 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -432,6 +432,11 @@ Les accesseurs '{0}' et '{1}' doivent tous deux être initialiseurs uniquement ou ne pas l'être + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Impossible d'utiliser l'expression donnée dans une instruction fixed @@ -977,6 +982,11 @@ La méthode '{0}' spécifie une contrainte 'default' pour le paramètre de type '{1}', mais le paramètre de type '{2}' correspondant de la méthode substituée ou explicitement implémentée '{3}' est limité à un type référence ou à un type valeur. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. La méthode '{0}' spécifie une contrainte 'class' pour le paramètre de type '{1}', mais le paramètre de type '{2}' correspondant de la méthode substituée ou explicitement implémentée '{3}' n'est pas un type référence. @@ -1087,6 +1097,26 @@ Les modèles relationnels ne peuvent pas être utilisés pour une valeur NaN à virgule flottante. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}' : le runtime cible ne prend pas en charge les types covariants dans les substitutions. Le type doit être '{2}' pour correspondre au membre substitué '{1}' @@ -1382,6 +1412,11 @@ structs d’enregistrement 'record structs' is not localizable. + + required members + required members + + sealed ToString in record ToString scellé dans l’enregistrement diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 3099d6cfab162..6bdd6d1fe5a71 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -432,6 +432,11 @@ Il tipo di sola inizializzazione può essere specificato per entrambe le funzioni di accesso '{0}' e '{1}' o per nessuna di esse + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Non è possibile usare l'espressione specificata in un'istruzione fixed @@ -977,6 +982,11 @@ Il metodo '{0}' specifica un vincolo 'default' per il parametro di tipo '{1}', ma il parametro di tipo corrispondente '{2}' del metodo '{3}' sottoposto a override o implementato in modo esplicito è vincolato a un tipo riferimento a un tipo valore. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Il metodo '{0}' specifica un vincolo 'class' per il parametro di tipo '{1}', ma il parametro di tipo corrispondente '{2}' del metodo '{3}' sottoposto a override o implementato in modo esplicito non è un tipo riferimento. @@ -1087,6 +1097,26 @@ Non è possibile usare i criteri relazionali per un valore NaN a virgola mobile. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': il runtime di destinazione non supporta tipi covarianti negli override. Il tipo deve essere '{2}' in modo da corrispondere al membro '{1}' di cui è stato eseguito l'override @@ -1382,6 +1412,11 @@ struct di record 'record structs' is not localizable. + + required members + required members + + sealed ToString in record ToString sealed nel record diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 5ded70e499670..ffb1a49ea0bb4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -432,6 +432,11 @@ アクセサー '{0}' と '{1}' は、両方 init 専用か、両方そうでないかのいずれかでなければなりません + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement 指定された式を fixed ステートメントで使用することはできません @@ -977,6 +982,11 @@ メソッド '{0}' は、型パラメーター '{1}' に対して 'default' 制約を指定していますが、オーバーライドされた、または明示的に実装されたメソッド '{3}' の対応する型パラメーター '{2}' は、参照型または値の型に制約されています。 + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. メソッド '{0}' は、型パラメーター '{1}' に対して 'class' 制約を指定していますが、オーバーライドされた、または明示的に実装されたメソッド '{3}' の対応する型パラメーター '{2}' は参照型ではありません。 @@ -1087,6 +1097,26 @@ リレーショナル パターンは、浮動小数点の NaN に使用することはできません。 + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': ターゲットのランタイムはオーバーライドで covariant 型をサポートしていません。型は、オーバーライドされるメンバー '{1}' と一致する '{2}' にする必要があります @@ -1382,6 +1412,11 @@ レコード構造体 'record structs' is not localizable. + + required members + required members + + sealed ToString in record レコードでシールされた ToString diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 0467b6f969aa3..23fad227a5071 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -432,6 +432,11 @@ '{0}' 및 '{1}' 접근자는 둘 다 초기값 전용이거나 둘 다 초기값 전용이 아니어야 합니다. + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement fixed 문에서는 지정된 식을 사용할 수 없습니다. @@ -977,6 +982,11 @@ 메서드 '{0}'이(가) 형식 매개 변수 '{1}'의 'default' 제약 조건을 지정하지만 재정의되었거나 명시적으로 구현된 메서드 '{3}'의 해당 형식 매개 변수 '{2}'이(가) 참조 형식 또는 값 형식으로 제한됩니다. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. '{0}' 메서드는 형식 매개 변수 '{1}'의 'class' 제약 조건을 지정하지만 재정의되었거나 명시적으로 구현된 '{3}' 메서드의 해당 형식 매개 변수 '{2}'이(가) 참조 형식이 아닙니다. @@ -1087,6 +1097,26 @@ 부동 소수점 NaN에는 관계형 패턴을 사용할 수 없습니다. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': 대상 런타임이 재정의에서 공변(covariant) 형식을 지원하지 않습니다. 재정의된 멤버 '{1}'과(와) 일치하려면 '{2}' 형식이어야 합니다. @@ -1382,6 +1412,11 @@ 레코드 구조체 'record structs' is not localizable. + + required members + required members + + sealed ToString in record 레코드의 봉인된 ToString diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 3d05f013a9aff..56990cd668e6d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -432,6 +432,11 @@ Tylko do inicjowania powinny być obie metody dostępu „{0}” i „{1}” albo żadna z nich + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Podanego wyrażenia nie można użyć w instrukcji fixed @@ -977,6 +982,11 @@ Metoda „{0}” określa ograniczenie „default” dla parametru typu „{1}”, lecz odpowiadający parametr typu „{2}” przesłoniętej lub jawnie zaimplementowanej metody „{3}” jest ograniczony do typu odwołania lub typu wartości. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Metoda „{0}” określa ograniczenie „class” dla parametru typu „{1}”, lecz odpowiadający parametr typu „{2}” przesłoniętej lub jawnie zaimplementowanej metody „{3}” nie jest typem referencyjnym. @@ -1087,6 +1097,26 @@ Wzorców relacyjnych nie można używać na potrzeby zmiennoprzecinkowej wartości NaN. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' „{0}”: docelowe środowisko uruchomieniowe nie obsługuje typów kowariantnych w przesłonięciach. Typem musi być „{2}”, aby zachować zgodność z przesłoniętą składową „{1}”. @@ -1382,6 +1412,11 @@ struktury rekordów 'record structs' is not localizable. + + required members + required members + + sealed ToString in record zapieczętowany obiekt ToString w rekordzie diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index be99a4c58d7cb..bb83790d13313 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -432,6 +432,11 @@ Os acessadores '{0}' e '{1}' devem ser somente de inicialização ou nenhum + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement A expressão determinada não pode ser usada em uma instrução fixed @@ -977,6 +982,11 @@ O método '{0}' especifica uma restrição 'default' para o parâmetro de tipo '{1}', mas o parâmetro de tipo correspondente '{2}' do método substituído ou implementado explicitamente '{3}' está restrito por um tipo de referência ou um tipo de valor. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. O método '{0}' especifica uma restrição de 'class' para o parâmetro de tipo '{1}', mas o parâmetro de tipo correspondente '{2}' do método substituído ou implementado explicitamente '{3}' não é um tipo de referência. @@ -1087,6 +1097,26 @@ Os padrões relacionais não podem ser usados para um NaN de ponto flutuante. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': o runtime de destino não dá suporte a tipos covariantes em substituições. O tipo precisa ser '{2}' para corresponder ao membro substituído '{1}' @@ -1382,6 +1412,11 @@ registrar structs 'record structs' is not localizable. + + required members + required members + + sealed ToString in record ToString selado no registro diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index e385c0a76ab08..86f3b39cb1899 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -432,6 +432,11 @@ Каждый из методов доступа "{0}" и "{1}" должен вызываться только во время инициализации либо ни один из этих методов доступа не должен вызываться таким образом. + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Заданное выражение невозможно использовать в операторе fixed @@ -977,6 +982,11 @@ Метод "{0}" задает ограничение "default" для параметра типа "{1}", но соответствующий параметр типа "{2}" переопределенного или явно реализованного метода "{3}" ограничен и может представлять собой только тип ссылки или тип значения. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Метод "{0}" задает ограничение class для параметра типа "{1}", но соответствующий параметр типа "{2}" переопределенного или явно реализованного метода "{3}" не является ссылочным типом. @@ -1087,6 +1097,26 @@ Реляционные шаблоны не могут использоваться для NaN с плавающей запятой. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' "{0}": целевая среда выполнения не поддерживает ковариантные типы в переопределениях. Для сопоставления переопределенного элемента "{1}" необходимо использовать тип "{2}". @@ -1382,6 +1412,11 @@ структуры записей 'record structs' is not localizable. + + required members + required members + + sealed ToString in record запечатанный ToString в записи diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index da8185fac7dfd..8d4394caf493b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -432,6 +432,11 @@ '{0}' ve '{1}' erişimcilerinin ikisi de yalnızca init olmalıdır ya da ikisi de olmamalıdır + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Belirtilen ifade, fixed deyiminde kullanılamıyor @@ -977,6 +982,11 @@ '{0}' metodu, '{1}' tür parametresi için bir 'default' kısıtlaması belirtiyor, ancak geçersiz kılınan veya açıkça uygulanan '{3}' metodunun karşılık gelen '{2}' tür parametresi bir başvuru türü veya değer türüyle kısıtlanmış. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. '{0}' yöntemi, '{1}' tür parametresi için bir 'class' kısıtlaması belirtiyor, ancak geçersiz kılınan veya açıkça uygulanan '{3}' yönteminin karşılık gelen '{2}' tür parametresi bir başvuru türü değil. @@ -1087,6 +1097,26 @@ İlişkisel desenler, kayan noktalı NaN için kullanılamaz. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': Hedef çalışma zamanı, geçersiz kılmalarda birlikte değişken türleri desteklemiyor. Tür, geçersiz kılınan '{1}' üyesiyle eşleşmek için '{2}' olmalıdır @@ -1382,6 +1412,11 @@ kayıt yapıları 'record structs' is not localizable. + + required members + required members + + sealed ToString in record kayıtta mühürlü ToString diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 9df925ab44fa9..d8ba71d3cf382 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -432,6 +432,11 @@ 访问器 {0} 和 {1} 应同时为 init-only,或两者都不是 + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement 给定表达式不能用于 fixed 语句中 @@ -977,6 +982,11 @@ 方法“{0}”为类型参数“{1}”指定了 "default" 约束,但被替代的或显式实现的方法“{3}”的对应类型参数“{2}” 仅限于引用类型或值类型。 + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. 方法 "{0}" 为类型参数 "{1}" 指定了 "class" 约束,但重写的或显式实现的方法 "{3}" 的对应类型参数 "{2}" 不是引用类型。 @@ -1087,6 +1097,26 @@ 关系模式可能不能用于浮点 NaN。 + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' “{0}”: 目标运行时不支持替代中的协变类型。类型必须为“{2}”才能匹配替代成员“{1}” @@ -1382,6 +1412,11 @@ 记录结构 'record structs' is not localizable. + + required members + required members + + sealed ToString in record 记录的密封 ToString diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index ae3bf3dadf94b..03669f0a62a8c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -432,6 +432,11 @@ 存取子 '{0}' 與 '{1}' 不得同時是或不是僅供初始化 + + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement 指定運算式無法用於 fixed 陳述式中 @@ -977,6 +982,11 @@ 方法 '{0}' 會為型別參數 '{1}' 指定 'default' 條件約束,但覆寫或明確實作方法 '{3}' 的對應型別參數 '{2}' 會限制為參考型別或實值型別。 + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. 方法 '{0}' 會為型別參數 '{1}' 指定 'class' 條件約束,但覆寫或明確實作的方法 '{3}' 對應型別參數 '{2}' 不屬於參考型別。 @@ -1087,6 +1097,26 @@ 浮點 NaN 不可使用關聯性模式。 + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. + + + + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': 在覆寫中,目標執行階段不支援 Covariant 類型。類型必須是 '{2}',才符合覆寫的成員 '{1}' @@ -1382,6 +1412,11 @@ 記錄結構 'record structs' is not localizable. + + required members + required members + + sealed ToString in record 記錄中有密封的 ToString diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index f1511be8f3a69..1b7aff577023d 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -610,6 +610,7 @@ public void AllWellKnownTypes() case WellKnownType.System_Runtime_CompilerServices_NativeIntegerAttribute: case WellKnownType.System_Runtime_CompilerServices_IsExternalInit: case WellKnownType.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler: + case WellKnownType.System_Runtime_CompilerServices_RequiredMemberAttribute: // Not yet in the platform. continue; case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation: @@ -964,6 +965,7 @@ public void AllWellKnownTypeMembers() case WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor: case WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags: case WellKnownMember.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear: + case WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor: // Not yet in the platform. continue; case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile: diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs index bdb7812c8f2d7..d5e358d3b6939 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs @@ -89,6 +89,8 @@ public override IEnumerable MemberNames } } + internal override bool HasDeclaredRequiredMembers => throw new NotImplementedException(); + public override ImmutableArray GetMembers() { return _children.AsImmutable(); diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs new file mode 100644 index 0000000000000..7d16b5d73599d --- /dev/null +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -0,0 +1,1092 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols; + +[CompilerTrait(CompilerFeature.RequiredMembers)] +public class RequiredMembersTests : CSharpTestBase +{ + private const string RequiredMemberAttribute = @" +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, Inherited = false, AllowMultiple = false)] + public class RequiredMemberAttribute : Attribute + { + public RequiredMemberAttribute() + { + } + } +} +"; + + private static CSharpCompilation CreateCompilationWithRequiredMembers(CSharpTestSource source, CSharpParseOptions? parseOptions = null, CSharpCompilationOptions? options = null, TargetFramework tfm = TargetFramework.NetCoreApp) + => CreateCompilation(new[] { source, RequiredMemberAttribute }, options: options, parseOptions: parseOptions); + + private static Action ValidateRequiredMembersInModule(string[] memberPaths, string expectedAttributeLayout) + { + return module => + { + if (module is PEModuleSymbol peModule) + { + var actualAttributes = RequiredMemberAttributesVisitor.GetString(peModule); + AssertEx.AssertEqualToleratingWhitespaceDifferences(expectedAttributeLayout, actualAttributes); + return; + } + + foreach (var memberPath in memberPaths) + { + var member = module.GlobalNamespace.GetMember(memberPath); + Assert.True(member is PropertySymbol or FieldSymbol, $"Unexpected member symbol type {member.Kind}"); + Assert.True(member.IsRequired()); + + if (module is SourceModuleSymbol) + { + Assert.All(member.GetAttributes(), attr => AssertEx.NotEqual("System.Runtime.CompilerServices.RequiredMemberAttribute", attr.AttributeClass.ToTestDisplayString())); + } + } + }; + } + + [Fact] + public void InvalidModifierLocations() + { + var comp = CreateCompilationWithRequiredMembers(@" +required class C1 +{ + required void M(required int i) + { + } + + required C1() { } + required ~C1() { } + + required int this[int i] { get => 0; set { } } + + int Prop1 { required get; } + int Prop2 { required set { } } +} +required struct S {} +required delegate void D(); +required interface I1 +{ + required int Prop3 { get; set; } + required int Field; +} +interface I2 +{ + public int Prop4 { get; } +} +class C2 : I2 +{ + required int I2.Prop4 => 0; +} +"); + + comp.VerifyDiagnostics( + // (2,16): error CS0106: The modifier 'required' is not valid for this item + // required class C1 + Diagnostic(ErrorCode.ERR_BadMemberFlag, "C1").WithArguments("required").WithLocation(2, 16), + // (4,19): error CS0106: The modifier 'required' is not valid for this item + // required void M(required int i) + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M").WithArguments("required").WithLocation(4, 19), + // (4,21): error CS0246: The type or namespace name 'required' could not be found (are you missing a using directive or an assembly reference?) + // required void M(required int i) + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "required").WithArguments("required").WithLocation(4, 21), + // (4,30): error CS1001: Identifier expected + // required void M(required int i) + Diagnostic(ErrorCode.ERR_IdentifierExpected, "int").WithLocation(4, 30), + // (4,30): error CS1003: Syntax error, ',' expected + // required void M(required int i) + Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments(",", "int").WithLocation(4, 30), + // (8,14): error CS0106: The modifier 'required' is not valid for this item + // required C1() { } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "C1").WithArguments("required").WithLocation(8, 14), + // (9,15): error CS0106: The modifier 'required' is not valid for this item + // required ~C1() { } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "C1").WithArguments("required").WithLocation(9, 15), + // (11,18): error CS0106: The modifier 'required' is not valid for this item + // required int this[int i] { get => 0; set { } } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("required").WithLocation(11, 18), + // (13,26): error CS0106: The modifier 'required' is not valid for this item + // int Prop1 { required get; } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("required").WithLocation(13, 26), + // (14,26): error CS0106: The modifier 'required' is not valid for this item + // int Prop2 { required set { } } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("required").WithLocation(14, 26), + // (16,17): error CS0106: The modifier 'required' is not valid for this item + // required struct S {} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "S").WithArguments("required").WithLocation(16, 17), + // (17,24): error CS0106: The modifier 'required' is not valid for this item + // required delegate void D(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "D").WithArguments("required").WithLocation(17, 24), + // (18,20): error CS0106: The modifier 'required' is not valid for this item + // required interface I1 + Diagnostic(ErrorCode.ERR_BadMemberFlag, "I1").WithArguments("required").WithLocation(18, 20), + // (20,18): error CS0106: The modifier 'required' is not valid for this item + // required int Prop3 { get; set; } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "Prop3").WithArguments("required").WithLocation(20, 18), + // (21,18): error CS0525: Interfaces cannot contain instance fields + // required int Field; + Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "Field").WithLocation(21, 18), + // (21,18): warning CS0649: Field 'I1.Field' is never assigned to, and will always have its default value 0 + // required int Field; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("I1.Field", "0").WithLocation(21, 18), + // (29,21): error CS0106: The modifier 'required' is not valid for this item + // required int I2.Prop4 => 0; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "Prop4").WithArguments("required").WithLocation(29, 21) + ); + } + + [Fact] + public void InvalidModifierCombinations() + { + var comp = CreateCompilationWithRequiredMembers(@" +unsafe struct C +{ + required const int F1 = 1; + required static int F2 = 2; + required static int P1 { get; set; } + required fixed int F3[10]; +} +", options: TestOptions.UnsafeReleaseDll); + + comp.VerifyDiagnostics( + // (4,24): error CS0106: The modifier 'required' is not valid for this item + // required const int F1 = 1; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "F1").WithArguments("required").WithLocation(4, 24), + // (5,25): error CS0106: The modifier 'required' is not valid for this item + // required static int F2 = 2; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "F2").WithArguments("required").WithLocation(5, 25), + // (5,25): warning CS0414: The field 'C.F2' is assigned but its value is never used + // required static int F2 = 2; + Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "F2").WithArguments("C.F2").WithLocation(5, 25), + // (6,25): error CS0106: The modifier 'required' is not valid for this item + // required static int P1 { get; set; } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P1").WithArguments("required").WithLocation(6, 25), + // (7,24): error CS0106: The modifier 'required' is not valid for this item + // required fixed int F3[10]; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "F3").WithArguments("required").WithLocation(7, 24) + ); + } + + [Fact] + public void LangVersion() + { + string code = @" +#pragma warning disable CS0649 // Field is never assigned +class C +{ + internal required int Field; + internal required int Prop { get; set; } +} +"; + var comp = CreateCompilationWithRequiredMembers(code, parseOptions: TestOptions.Regular10); + + comp.VerifyDiagnostics( + // (5,27): error CS8652: The feature 'required members' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // internal required int Field; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Field").WithArguments("required members").WithLocation(5, 27), + // (6,27): error CS8652: The feature 'required members' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // internal required int Prop { get; set; } + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop").WithArguments("required members").WithLocation(6, 27) + ); + + comp = CreateCompilationWithRequiredMembers(code, parseOptions: TestOptions.RegularNext); + comp.VerifyDiagnostics(); + } + + [Fact] + public void DuplicateKeyword() + { + var comp = CreateCompilationWithRequiredMembers(@" +class C +{ + internal required required int Field; + internal required required int Prop { get; set; } +} +"); + + comp.VerifyDiagnostics( + // (4,23): error CS1004: Duplicate 'required' modifier + // internal required required int Field; + Diagnostic(ErrorCode.ERR_DuplicateModifier, "required").WithArguments("required").WithLocation(4, 23), + // (4,36): warning CS0649: Field 'C.Field' is never assigned to, and will always have its default value 0 + // internal required required int Field; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("C.Field", "0").WithLocation(4, 36), + // (5,23): error CS1004: Duplicate 'required' modifier + // internal required required int Prop { get; set; } + Diagnostic(ErrorCode.ERR_DuplicateModifier, "required").WithArguments("required").WithLocation(5, 23) + ); + } + + [Theory] + [CombinatorialData] + public void InvalidNames(bool use10) + { + string code = @" +namespace N1 +{ + struct required {} +} +namespace N2 +{ + class required {} +} +namespace N3 +{ + interface required {} +} +namespace N4 +{ + delegate void required(); +} +namespace N5 +{ + record required(); +} +namespace N6 +{ + record struct required(); +} +namespace N7 +{ + class C + { + class required {} + } +} +namespace N8 +{ + class required {} +} +"; + var comp = CreateCompilationWithRequiredMembers(code, parseOptions: use10 ? TestOptions.Regular10 : TestOptions.RegularNext); + + comp.VerifyDiagnostics( + use10 ? + new[] + { + // (4,12): warning CS8981: The type name 'required' only contains lower-cased ascii characters. Such names may become reserved for the language. + // struct required {} + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "required").WithArguments("required").WithLocation(4, 12), + // (8,11): warning CS8981: The type name 'required' only contains lower-cased ascii characters. Such names may become reserved for the language. + // class required {} + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "required").WithArguments("required").WithLocation(8, 11), + // (12,15): warning CS8981: The type name 'required' only contains lower-cased ascii characters. Such names may become reserved for the language. + // interface required {} + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "required").WithArguments("required").WithLocation(12, 15), + // (16,19): warning CS8981: The type name 'required' only contains lower-cased ascii characters. Such names may become reserved for the language. + // delegate void required(); + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "required").WithArguments("required").WithLocation(16, 19), + // (20,12): warning CS8981: The type name 'required' only contains lower-cased ascii characters. Such names may become reserved for the language. + // record required(); + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "required").WithArguments("required").WithLocation(20, 12), + // (24,19): warning CS8981: The type name 'required' only contains lower-cased ascii characters. Such names may become reserved for the language. + // record struct required(); + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "required").WithArguments("required").WithLocation(24, 19), + // (30,15): warning CS8981: The type name 'required' only contains lower-cased ascii characters. Such names may become reserved for the language. + // class required {} + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "required").WithArguments("required").WithLocation(30, 15), + // (35,11): warning CS8981: The type name 'required' only contains lower-cased ascii characters. Such names may become reserved for the language. + // class required {} + Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "required").WithArguments("required").WithLocation(35, 11) + } : + new[] + { + // (4,12): error CS9500: Types and aliases cannot be named 'required'. + // struct required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(4, 12), + // (8,11): error CS9500: Types and aliases cannot be named 'required'. + // class required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(8, 11), + // (12,15): error CS9500: Types and aliases cannot be named 'required'. + // interface required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(12, 15), + // (16,19): error CS9500: Types and aliases cannot be named 'required'. + // delegate void required(); + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(16, 19), + // (20,12): error CS9500: Types and aliases cannot be named 'required'. + // record required(); + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(20, 12), + // (24,19): error CS9500: Types and aliases cannot be named 'required'. + // record struct required(); + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(24, 19), + // (30,15): error CS9500: Types and aliases cannot be named 'required'. + // class required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(30, 15), + // (35,11): error CS9500: Types and aliases cannot be named 'required'. + // class required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(35, 11) + } + ); + + code = code.Replace("required", "@required"); + comp = CreateCompilationWithRequiredMembers(code, parseOptions: use10 ? TestOptions.Regular10 : TestOptions.RegularNext); + comp.VerifyDiagnostics(); + } + + [Fact] + public void MissingRequiredMemberAttribute() + { + var comp = CreateCompilation(@" +class C +{ + public required int I { get; set; } +}"); + + // (2,7): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.RequiredMemberAttribute..ctor' + // class C + var expected = Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "C").WithArguments("System.Runtime.CompilerServices.RequiredMemberAttribute", ".ctor").WithLocation(2, 7); + comp.VerifyDiagnostics(expected); + comp.VerifyEmitDiagnostics(expected); + } + + [Fact] + public void MissingRequiredMemberAttributeCtor() + { + var comp = CreateCompilation(@" +class C +{ + public required int I { get; set; } +} + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] + public class RequiredMemberAttribute : Attribute + { + public RequiredMemberAttribute(int i) {} + } +} +"); + + // (2,7): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.RequiredMemberAttribute..ctor' + // class C + var expected = Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "C").WithArguments("System.Runtime.CompilerServices.RequiredMemberAttribute", ".ctor").WithLocation(2, 7); + comp.VerifyDiagnostics(expected); + comp.VerifyEmitDiagnostics(expected); + } + + [Fact] + public void RequiredMemberAttributeEmitted() + { + var comp = CreateCompilationWithRequiredMembers(@" +class C +{ + public required int Prop { get; set; } + public required int Field; +} +"); + + var expectedRequiredMembers = new[] { "C.Prop", "C.Field" }; + + var expectedAttributeLayout = @" +[RequiredMember] C + [RequiredMember] System.Int32 C.Field + [RequiredMember] System.Int32 C.Prop { get; set; } +"; + + var symbolValidator = ValidateRequiredMembersInModule(expectedRequiredMembers, expectedAttributeLayout); + var verifier = CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); + verifier.VerifyDiagnostics( + // (5,25): warning CS0649: Field 'C.Field' is never assigned to, and will always have its default value 0 + // public required int Field; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("C.Field", "0").WithLocation(5, 25) + ); + } + + [Fact] + public void RequiredMemberAttributeEmitted_OverrideRequiredProperty_MissingRequiredOnOverride01() + { + var comp = CreateCompilationWithRequiredMembers(@" +class Base +{ + public virtual required int Prop { get; set; } +} +class Derived : Base +{ + public override int Prop { get; set; } +} +"); + + comp.VerifyDiagnostics( + // (8,25): error CS9501: 'Derived.Prop': cannot remove 'required' from 'Base.Prop' when overriding + // public override int Prop { get; set; } + Diagnostic(ErrorCode.ERR_OverrideMustHaveRequired, "Prop").WithArguments("Derived.Prop", "Base.Prop").WithLocation(8, 25) + ); + } + + [Fact] + public void RequiredMemberAttributeEmitted_OverrideRequiredProperty_MissingRequiredOnOverride02() + { + var comp = CreateCompilationWithRequiredMembers(@" +class Base +{ + public virtual int Prop { get; set; } +} +class Derived : Base +{ + public override required int Prop { get; set; } +} +class DerivedDerived : Derived +{ + public override int Prop { get; set; } +} +"); + + comp.VerifyDiagnostics( + // (12,25): error CS9501: 'DerivedDerived.Prop': cannot remove 'required' from 'Derived.Prop' when overriding + // public override int Prop { get; set; } + Diagnostic(ErrorCode.ERR_OverrideMustHaveRequired, "Prop").WithArguments("DerivedDerived.Prop", "Derived.Prop").WithLocation(12, 25) + ); + } + + [Fact] + public void RequiredMemberAttributeEmitted_OverrideRequiredProperty() + { + var comp = CreateCompilationWithRequiredMembers(@" +class Base +{ + public virtual required int Prop { get; set; } +} +class Derived : Base +{ + public override required int Prop { get; set; } +} +"); + + var expectedRequiredMembers = new[] { "Base.Prop", "Derived.Prop" }; + + var expectedAttributeLayout = @" +[RequiredMember] Base + [RequiredMember] System.Int32 Base.Prop { get; set; } +[RequiredMember] Derived + [RequiredMember] System.Int32 Derived.Prop { get; set; }"; + + var symbolValidator = ValidateRequiredMembersInModule(expectedRequiredMembers, expectedAttributeLayout); + var verifier = CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); + verifier.VerifyDiagnostics(); + } + + [Fact] + public void RequiredMemberAttributeEmitted_AddRequiredOnOverride() + { + var comp = CreateCompilationWithRequiredMembers(@" +class Base +{ + public virtual int Prop { get; set; } +} +class Derived : Base +{ + public override required int Prop { get; set; } +} +class DerivedDerived : Derived +{ + public override required int Prop { get; set; } +} +"); + + var expectedRequiredMembers = new[] { "Derived.Prop", "DerivedDerived.Prop" }; + + var expectedAttributeLayout = @" +[RequiredMember] Derived + [RequiredMember] System.Int32 Derived.Prop { get; set; } +[RequiredMember] DerivedDerived + [RequiredMember] System.Int32 DerivedDerived.Prop { get; set; } +"; + + var symbolValidator = ValidateRequiredMembersInModule(expectedRequiredMembers, expectedAttributeLayout); + var verifier = CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); + verifier.VerifyDiagnostics(); + } + + [Fact] + public void RequiredMemberAttributeEmitted_NestedTypeHasRequired() + { + var comp = CreateCompilationWithRequiredMembers(@" +class Outer +{ + class Inner + { + public required int Prop { get; set; } + public required int Field; + } +} +"); + + var expectedRequiredMembers = new[] { "Outer.Inner.Prop", "Outer.Inner.Field" }; + + var expectedAttributeLayout = @" +Outer + [RequiredMember] Outer.Inner + [RequiredMember] System.Int32 Outer.Inner.Field + [RequiredMember] System.Int32 Outer.Inner.Prop { get; set; }"; + + var symbolValidator = ValidateRequiredMembersInModule(expectedRequiredMembers, expectedAttributeLayout); + var verifier = CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); + verifier.VerifyDiagnostics( + // (7,29): warning CS0649: Field 'Outer.Inner.Field' is never assigned to, and will always have its default value 0 + // public required int Field; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("Outer.Inner.Field", "0").WithLocation(7, 29) + ); + } + + [Fact] + public void RequiredMemberAttributeEmitted_AbstractProperty() + { + var comp = CreateCompilationWithRequiredMembers(@" +abstract class Base +{ + public required abstract int Prop { get; set; } +} +class Derived : Base +{ + public override required int Prop { get; set; } +} +"); + + var expectedRequiredMembers = new[] { "Base.Prop", "Derived.Prop" }; + + var expectedAttributeLayout = @" +[RequiredMember] Base + [RequiredMember] System.Int32 Base.Prop { get; set; } +[RequiredMember] Derived + [RequiredMember] System.Int32 Derived.Prop { get; set; } +"; + + var symbolValidator = ValidateRequiredMembersInModule(expectedRequiredMembers, expectedAttributeLayout); + var verifier = CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); + verifier.VerifyDiagnostics(); + } + + [Fact] + public void HidingRequiredMembers() + { + var comp = CreateCompilationWithRequiredMembers(@" +#pragma warning disable CS0649 // Never assigned +class Base +{ + public required int Field; + public required int Prop { get; set; } +} +class Derived1 : Base +{ + public new int Field; // 1 + public new int Prop { get; set; } // 2 +} +class Derived2 : Base +{ + public new int Prop; // 3 + public new int Field { get; set; } // 4 +} +class Derived3 : Base +{ + public int Field; // 1 + public int Prop { get; set; } // 2 +} +"); + + comp.VerifyDiagnostics( + // (10,20): error CS9502: Required member 'Base.Field' cannot be hidden by 'Derived1.Field'. + // public new int Field; // 1 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeHidden, "Field").WithArguments("Base.Field", "Derived1.Field").WithLocation(10, 20), + // (11,20): error CS9502: Required member 'Base.Prop' cannot be hidden by 'Derived1.Prop'. + // public new int Prop { get; set; } // 2 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeHidden, "Prop").WithArguments("Base.Prop", "Derived1.Prop").WithLocation(11, 20), + // (15,20): error CS9502: Required member 'Base.Prop' cannot be hidden by 'Derived2.Prop'. + // public new int Prop; // 3 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeHidden, "Prop").WithArguments("Base.Prop", "Derived2.Prop").WithLocation(15, 20), + // (16,20): error CS9502: Required member 'Base.Field' cannot be hidden by 'Derived2.Field'. + // public new int Field { get; set; } // 4 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeHidden, "Field").WithArguments("Base.Field", "Derived2.Field").WithLocation(16, 20), + // (20,16): warning CS0108: 'Derived3.Field' hides inherited member 'Base.Field'. Use the new keyword if hiding was intended. + // public int Field; // 1 + Diagnostic(ErrorCode.WRN_NewRequired, "Field").WithArguments("Derived3.Field", "Base.Field").WithLocation(20, 16), + // (20,16): error CS9502: Required member 'Base.Field' cannot be hidden by 'Derived3.Field'. + // public int Field; // 1 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeHidden, "Field").WithArguments("Base.Field", "Derived3.Field").WithLocation(20, 16), + // (21,16): error CS9502: Required member 'Base.Prop' cannot be hidden by 'Derived3.Prop'. + // public int Prop { get; set; } // 2 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeHidden, "Prop").WithArguments("Base.Prop", "Derived3.Prop").WithLocation(21, 16) + ); + } + + [Fact] + public void RequiredMembersMustBeAsVisibleAsContainingType() + { + var comp = CreateCompilationWithRequiredMembers(@" +#pragma warning disable CS0649 // Never assigned +#pragma warning disable CS0169 // Never used +public class PublicClass +{ + public required int PublicProperty { get; set; } + internal protected required int InternalProtectedProperty { get; set; } // 1 + internal required int InternalProperty { get; set; } // 2 + protected required int ProtectedProperty { get; set; } // 3 + private protected required int PrivateProtectedProperty { get; set; } // 4 + private required int PrivateProperty { get; set; } // 5 + public required int PublicField; + internal protected required int InternalProtectedField; // 6 + internal required int InternalField; // 7 + protected required int ProtectedField; // 8 + private protected required int PrivateProtectedField; // 9 + private required int PrivateField; // 10 +} +internal class InternalClass +{ + public required int PublicProperty { get; set; } + internal protected required int InternalProtectedProperty { get; set; } + internal required int InternalProperty { get; set; } + protected required int ProtectedProperty { get; set; } // 11 + private protected required int PrivateProtectedProperty { get; set; } // 12 + private required int PrivateProperty { get; set; } // 13 + public required int PublicField; + internal protected required int InternalProtectedField; + internal required int InternalField; + protected required int ProtectedField; // 14 + private protected required int PrivateProtectedField; // 15 + private required int PrivateField; // 16 +} +internal class Outer +{ + protected internal class ProtectedInternalClass + { + public required int PublicProperty { get; set; } + internal protected required int InternalProtectedProperty { get; set; } + internal required int InternalProperty { get; set; } // 17 + protected required int ProtectedProperty { get; set; } // 18 + private protected required int PrivateProtectedProperty { get; set; } // 19 + private required int PrivateProperty { get; set; } // 20 + public required int PublicField; + internal protected required int InternalProtectedField; + internal required int InternalField; // 21 + protected required int ProtectedField; // 22 + private protected required int PrivateProtectedField; // 23 + private required int PrivateField; // 24 + } + protected class ProtectedClass + { + public required int PublicProperty { get; set; } + internal protected required int InternalProtectedProperty { get; set; } + internal required int InternalProperty { get; set; } + protected required int ProtectedProperty { get; set; } + private protected required int PrivateProtectedProperty { get; set; } // 25 + private required int PrivateProperty { get; set; } // 26 + public required int PublicField; + internal protected required int InternalProtectedField; + internal required int InternalField; + protected required int ProtectedField; + private protected required int PrivateProtectedField; // 27 + private required int PrivateField; // 28 + } + private protected class PrivateProtectedClass + { + public required int PublicProperty { get; set; } + internal protected required int InternalProtectedProperty { get; set; } + internal required int InternalProperty { get; set; } + protected required int ProtectedProperty { get; set; } + private protected required int PrivateProtectedProperty { get; set; } + private required int PrivateProperty { get; set; } // 29 + public required int PublicField; + internal protected required int InternalProtectedField; + internal required int InternalField; + protected required int ProtectedField; + private protected required int PrivateProtectedField; + private required int PrivateField; // 30 + } + private class PrivateClass + { + public required int PublicProperty { get; set; } + internal protected required int InternalProtectedProperty { get; set; } + internal required int InternalProperty { get; set; } + protected required int ProtectedProperty { get; set; } + private protected required int PrivateProtectedProperty { get; set; } + private required int PrivateProperty { get; set; } + public required int PublicField; + internal protected required int InternalProtectedField; + internal required int InternalField; + protected required int ProtectedField; + private protected required int PrivateProtectedField; + private required int PrivateField; + } +} +"); + + comp.VerifyDiagnostics( + // (7,37): error CS9503: Required member 'PublicClass.InternalProtectedProperty' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // internal protected required int InternalProtectedProperty { get; set; } // 1 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "InternalProtectedProperty").WithArguments("PublicClass.InternalProtectedProperty", "PublicClass").WithLocation(7, 37), + // (8,27): error CS9503: Required member 'PublicClass.InternalProperty' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // internal required int InternalProperty { get; set; } // 2 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "InternalProperty").WithArguments("PublicClass.InternalProperty", "PublicClass").WithLocation(8, 27), + // (9,28): error CS9503: Required member 'PublicClass.ProtectedProperty' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // protected required int ProtectedProperty { get; set; } // 3 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "ProtectedProperty").WithArguments("PublicClass.ProtectedProperty", "PublicClass").WithLocation(9, 28), + // (10,36): error CS9503: Required member 'PublicClass.PrivateProtectedProperty' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // private protected required int PrivateProtectedProperty { get; set; } // 4 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("PublicClass.PrivateProtectedProperty", "PublicClass").WithLocation(10, 36), + // (11,26): error CS9503: Required member 'PublicClass.PrivateProperty' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // private required int PrivateProperty { get; set; } // 5 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("PublicClass.PrivateProperty", "PublicClass").WithLocation(11, 26), + // (13,37): error CS9503: Required member 'PublicClass.InternalProtectedField' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // internal protected required int InternalProtectedField; // 6 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "InternalProtectedField").WithArguments("PublicClass.InternalProtectedField", "PublicClass").WithLocation(13, 37), + // (14,27): error CS9503: Required member 'PublicClass.InternalField' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // internal required int InternalField; // 7 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "InternalField").WithArguments("PublicClass.InternalField", "PublicClass").WithLocation(14, 27), + // (15,28): error CS9503: Required member 'PublicClass.ProtectedField' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // protected required int ProtectedField; // 8 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "ProtectedField").WithArguments("PublicClass.ProtectedField", "PublicClass").WithLocation(15, 28), + // (16,36): error CS9503: Required member 'PublicClass.PrivateProtectedField' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // private protected required int PrivateProtectedField; // 9 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("PublicClass.PrivateProtectedField", "PublicClass").WithLocation(16, 36), + // (17,26): error CS9503: Required member 'PublicClass.PrivateField' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // private required int PrivateField; // 10 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("PublicClass.PrivateField", "PublicClass").WithLocation(17, 26), + // (24,28): error CS9503: Required member 'InternalClass.ProtectedProperty' cannot be less visible or have a setter less visible than the containing type 'InternalClass'. + // protected required int ProtectedProperty { get; set; } // 11 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "ProtectedProperty").WithArguments("InternalClass.ProtectedProperty", "InternalClass").WithLocation(24, 28), + // (25,36): error CS9503: Required member 'InternalClass.PrivateProtectedProperty' cannot be less visible or have a setter less visible than the containing type 'InternalClass'. + // private protected required int PrivateProtectedProperty { get; set; } // 12 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("InternalClass.PrivateProtectedProperty", "InternalClass").WithLocation(25, 36), + // (26,26): error CS9503: Required member 'InternalClass.PrivateProperty' cannot be less visible or have a setter less visible than the containing type 'InternalClass'. + // private required int PrivateProperty { get; set; } // 13 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("InternalClass.PrivateProperty", "InternalClass").WithLocation(26, 26), + // (30,28): error CS9503: Required member 'InternalClass.ProtectedField' cannot be less visible or have a setter less visible than the containing type 'InternalClass'. + // protected required int ProtectedField; // 14 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "ProtectedField").WithArguments("InternalClass.ProtectedField", "InternalClass").WithLocation(30, 28), + // (31,36): error CS9503: Required member 'InternalClass.PrivateProtectedField' cannot be less visible or have a setter less visible than the containing type 'InternalClass'. + // private protected required int PrivateProtectedField; // 15 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("InternalClass.PrivateProtectedField", "InternalClass").WithLocation(31, 36), + // (32,26): error CS9503: Required member 'InternalClass.PrivateField' cannot be less visible or have a setter less visible than the containing type 'InternalClass'. + // private required int PrivateField; // 16 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("InternalClass.PrivateField", "InternalClass").WithLocation(32, 26), + // (40,31): error CS9503: Required member 'Outer.ProtectedInternalClass.InternalProperty' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedInternalClass'. + // internal required int InternalProperty { get; set; } // 17 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "InternalProperty").WithArguments("Outer.ProtectedInternalClass.InternalProperty", "Outer.ProtectedInternalClass").WithLocation(40, 31), + // (41,32): error CS9503: Required member 'Outer.ProtectedInternalClass.ProtectedProperty' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedInternalClass'. + // protected required int ProtectedProperty { get; set; } // 18 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "ProtectedProperty").WithArguments("Outer.ProtectedInternalClass.ProtectedProperty", "Outer.ProtectedInternalClass").WithLocation(41, 32), + // (42,40): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateProtectedProperty' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedInternalClass'. + // private protected required int PrivateProtectedProperty { get; set; } // 19 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("Outer.ProtectedInternalClass.PrivateProtectedProperty", "Outer.ProtectedInternalClass").WithLocation(42, 40), + // (43,30): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateProperty' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedInternalClass'. + // private required int PrivateProperty { get; set; } // 20 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("Outer.ProtectedInternalClass.PrivateProperty", "Outer.ProtectedInternalClass").WithLocation(43, 30), + // (46,31): error CS9503: Required member 'Outer.ProtectedInternalClass.InternalField' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedInternalClass'. + // internal required int InternalField; // 21 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "InternalField").WithArguments("Outer.ProtectedInternalClass.InternalField", "Outer.ProtectedInternalClass").WithLocation(46, 31), + // (47,32): error CS9503: Required member 'Outer.ProtectedInternalClass.ProtectedField' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedInternalClass'. + // protected required int ProtectedField; // 22 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "ProtectedField").WithArguments("Outer.ProtectedInternalClass.ProtectedField", "Outer.ProtectedInternalClass").WithLocation(47, 32), + // (48,40): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateProtectedField' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedInternalClass'. + // private protected required int PrivateProtectedField; // 23 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("Outer.ProtectedInternalClass.PrivateProtectedField", "Outer.ProtectedInternalClass").WithLocation(48, 40), + // (49,30): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateField' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedInternalClass'. + // private required int PrivateField; // 24 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("Outer.ProtectedInternalClass.PrivateField", "Outer.ProtectedInternalClass").WithLocation(49, 30), + // (57,40): error CS9503: Required member 'Outer.ProtectedClass.PrivateProtectedProperty' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedClass'. + // private protected required int PrivateProtectedProperty { get; set; } // 25 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("Outer.ProtectedClass.PrivateProtectedProperty", "Outer.ProtectedClass").WithLocation(57, 40), + // (58,30): error CS9503: Required member 'Outer.ProtectedClass.PrivateProperty' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedClass'. + // private required int PrivateProperty { get; set; } // 26 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("Outer.ProtectedClass.PrivateProperty", "Outer.ProtectedClass").WithLocation(58, 30), + // (63,40): error CS9503: Required member 'Outer.ProtectedClass.PrivateProtectedField' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedClass'. + // private protected required int PrivateProtectedField; // 27 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("Outer.ProtectedClass.PrivateProtectedField", "Outer.ProtectedClass").WithLocation(63, 40), + // (64,30): error CS9503: Required member 'Outer.ProtectedClass.PrivateField' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedClass'. + // private required int PrivateField; // 28 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("Outer.ProtectedClass.PrivateField", "Outer.ProtectedClass").WithLocation(64, 30), + // (73,30): error CS9503: Required member 'Outer.PrivateProtectedClass.PrivateProperty' cannot be less visible or have a setter less visible than the containing type 'Outer.PrivateProtectedClass'. + // private required int PrivateProperty { get; set; } // 29 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("Outer.PrivateProtectedClass.PrivateProperty", "Outer.PrivateProtectedClass").WithLocation(73, 30), + // (79,30): error CS9503: Required member 'Outer.PrivateProtectedClass.PrivateField' cannot be less visible or have a setter less visible than the containing type 'Outer.PrivateProtectedClass'. + // private required int PrivateField; // 30 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("Outer.PrivateProtectedClass.PrivateField", "Outer.PrivateProtectedClass").WithLocation(79, 30) + ); + } + + [Fact] + public void RequiredMembersMustBeAsVisibleAsContainingType_InaccessibleSetters() + { + var comp = CreateCompilationWithRequiredMembers(@" +public class PublicClass +{ + public required int InternalProtected { get; internal protected set; } // 1 + public required int Internal { get; internal set; } // 2 + public required int Protected { get; protected set; } // 3 + public required int PrivateProtected { get; private protected set; } // 4 + public required int Private { get; private set; } // 5 +} +internal class InternalClass +{ + public required int InternalProtected { get; internal protected set; } + public required int Internal { get; internal set; } + public required int Protected { get; protected set; } // 6 + public required int PrivateProtected { get; private protected set; } // 7 + public required int Private { get; private set; } // 8 +} +internal class Outer +{ + protected internal class InternalProtectedClass + { + public required int InternalProtected { get; internal protected set; } + public required int Internal { get; internal set; } // 9 + public required int Protected { get; protected set; } // 10 + public required int PrivateProtected { get; private protected set; } // 11 + public required int Private { get; private set; } // 12 + } + protected class ProtectedClass + { + public required int InternalProtected { get; internal protected set; } + public required int Internal { get; internal set; } + public required int Protected { get; protected set; } + public required int PrivateProtected { get; private protected set; } // 13 + public required int Private { get; private set; } // 14 + } + private protected class PrivateProtectedClass + { + public required int InternalProtected { get; internal protected set; } + public required int Internal { get; internal set; } + public required int Protected { get; protected set; } + public required int PrivateProtected { get; private protected set; } + public required int Private { get; private set; } // 15 + } + private class PrivateClass + { + public required int InternalProtected { get; internal protected set; } + public required int Internal { get; internal set; } + public required int Protected { get; protected set; } + public required int PrivateProtected { get; private protected set; } + public required int Private { get; private set; } + } +} +"); + + comp.VerifyDiagnostics( + // (4,25): error CS9503: Required member 'PublicClass.InternalProtected' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // public required int InternalProtected { get; internal protected set; } // 1 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "InternalProtected").WithArguments("PublicClass.InternalProtected", "PublicClass").WithLocation(4, 25), + // (5,25): error CS9503: Required member 'PublicClass.Internal' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // public required int Internal { get; internal set; } // 2 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Internal").WithArguments("PublicClass.Internal", "PublicClass").WithLocation(5, 25), + // (6,25): error CS9503: Required member 'PublicClass.Protected' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // public required int Protected { get; protected set; } // 3 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Protected").WithArguments("PublicClass.Protected", "PublicClass").WithLocation(6, 25), + // (7,25): error CS9503: Required member 'PublicClass.PrivateProtected' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // public required int PrivateProtected { get; private protected set; } // 4 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtected").WithArguments("PublicClass.PrivateProtected", "PublicClass").WithLocation(7, 25), + // (8,25): error CS9503: Required member 'PublicClass.Private' cannot be less visible or have a setter less visible than the containing type 'PublicClass'. + // public required int Private { get; private set; } // 5 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Private").WithArguments("PublicClass.Private", "PublicClass").WithLocation(8, 25), + // (14,25): error CS9503: Required member 'InternalClass.Protected' cannot be less visible or have a setter less visible than the containing type 'InternalClass'. + // public required int Protected { get; protected set; } // 6 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Protected").WithArguments("InternalClass.Protected", "InternalClass").WithLocation(14, 25), + // (15,25): error CS9503: Required member 'InternalClass.PrivateProtected' cannot be less visible or have a setter less visible than the containing type 'InternalClass'. + // public required int PrivateProtected { get; private protected set; } // 7 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtected").WithArguments("InternalClass.PrivateProtected", "InternalClass").WithLocation(15, 25), + // (16,25): error CS9503: Required member 'InternalClass.Private' cannot be less visible or have a setter less visible than the containing type 'InternalClass'. + // public required int Private { get; private set; } // 8 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Private").WithArguments("InternalClass.Private", "InternalClass").WithLocation(16, 25), + // (23,29): error CS9503: Required member 'Outer.InternalProtectedClass.Internal' cannot be less visible or have a setter less visible than the containing type 'Outer.InternalProtectedClass'. + // public required int Internal { get; internal set; } // 9 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Internal").WithArguments("Outer.InternalProtectedClass.Internal", "Outer.InternalProtectedClass").WithLocation(23, 29), + // (24,29): error CS9503: Required member 'Outer.InternalProtectedClass.Protected' cannot be less visible or have a setter less visible than the containing type 'Outer.InternalProtectedClass'. + // public required int Protected { get; protected set; } // 10 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Protected").WithArguments("Outer.InternalProtectedClass.Protected", "Outer.InternalProtectedClass").WithLocation(24, 29), + // (25,29): error CS9503: Required member 'Outer.InternalProtectedClass.PrivateProtected' cannot be less visible or have a setter less visible than the containing type 'Outer.InternalProtectedClass'. + // public required int PrivateProtected { get; private protected set; } // 11 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtected").WithArguments("Outer.InternalProtectedClass.PrivateProtected", "Outer.InternalProtectedClass").WithLocation(25, 29), + // (26,29): error CS9503: Required member 'Outer.InternalProtectedClass.Private' cannot be less visible or have a setter less visible than the containing type 'Outer.InternalProtectedClass'. + // public required int Private { get; private set; } // 12 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Private").WithArguments("Outer.InternalProtectedClass.Private", "Outer.InternalProtectedClass").WithLocation(26, 29), + // (33,29): error CS9503: Required member 'Outer.ProtectedClass.PrivateProtected' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedClass'. + // public required int PrivateProtected { get; private protected set; } // 13 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "PrivateProtected").WithArguments("Outer.ProtectedClass.PrivateProtected", "Outer.ProtectedClass").WithLocation(33, 29), + // (34,29): error CS9503: Required member 'Outer.ProtectedClass.Private' cannot be less visible or have a setter less visible than the containing type 'Outer.ProtectedClass'. + // public required int Private { get; private set; } // 14 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Private").WithArguments("Outer.ProtectedClass.Private", "Outer.ProtectedClass").WithLocation(34, 29), + // (42,29): error CS9503: Required member 'Outer.PrivateProtectedClass.Private' cannot be less visible or have a setter less visible than the containing type 'Outer.PrivateProtectedClass'. + // public required int Private { get; private set; } // 15 + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Private").WithArguments("Outer.PrivateProtectedClass.Private", "Outer.PrivateProtectedClass").WithLocation(42, 29) + ); + } + + [Fact] + public void UsingRequiredMemberAttributeExplicitly() + { + var comp = CreateCompilationWithRequiredMembers(@" +using System.Runtime.CompilerServices; +[RequiredMember] +class C +{ + [RequiredMember] + public int Prop { get; set; } + [RequiredMember] + public int Field; +} +"); + + comp.VerifyDiagnostics( + // (3,2): error CS9504: Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + // [RequiredMember] + Diagnostic(ErrorCode.ERR_ExplicitRequiredMember, "RequiredMember").WithLocation(3, 2), + // (6,6): error CS9504: Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + // [RequiredMember] + Diagnostic(ErrorCode.ERR_ExplicitRequiredMember, "RequiredMember").WithLocation(6, 6), + // (8,6): error CS9504: Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + // [RequiredMember] + Diagnostic(ErrorCode.ERR_ExplicitRequiredMember, "RequiredMember").WithLocation(8, 6), + // (9,16): warning CS0649: Field 'C.Field' is never assigned to, and will always have its default value 0 + // public int Field; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("C.Field", "0").WithLocation(9, 16) + ); + + var prop = comp.SourceModule.GlobalNamespace.GetMember("C.Prop"); + Assert.False(prop.IsRequired); + } + + [Fact] + public void UsingRequiredMemberAttributeExplicitly_WrongLocations() + { + var comp = CreateCompilation(@" +using System; +using System.Runtime.CompilerServices; +class C +{ + [RequiredMember] + void M() {} + [RequiredMember] + event Action E; + [RequiredMember] + C() {} + [RequiredMember] + ~C() {} + [return: RequiredMember] + void M<[RequiredMember] T>([RequiredMember] int i) {} +} + +namespace System.Runtime.CompilerServices +{ + public class RequiredMemberAttribute : Attribute + { + public RequiredMemberAttribute() + { + } + } +} +"); + + comp.VerifyDiagnostics( + // (9,18): warning CS0067: The event 'C.E' is never used + // event Action E; + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E").WithArguments("C.E").WithLocation(9, 18) + ); + } + + [Fact] + public void RequiredWithInitializer() + { + var comp = CreateCompilationWithRequiredMembers(@" +class C +{ + public required int Field = 1; + public required int Prop { get; set; } = 1; +} +"); + + // PROTOTYPE(req): Confirm with LDM whether we want a warning here. + comp.VerifyDiagnostics(); + } + + [Fact] + public void RefReturningProperties() + { + var comp = CreateCompilationWithRequiredMembers(@" +class C +{ + private int i; + public required ref int Prop => ref i; +} +"); + + // PROTOTYPE(req): Confirm with LDM whether we want an error here. + comp.VerifyDiagnostics( + // (5,29): error CS9505: Required member 'C.Prop' must be settable. + // public required ref int Prop => ref i; + Diagnostic(ErrorCode.ERR_RequiredMemberMustBeSettable, "Prop").WithArguments("C.Prop").WithLocation(5, 29) + ); + } + + [Fact] + public void UnsettableMembers() + { + var comp = CreateCompilationWithRequiredMembers(@" +#pragma warning disable CS0649 // Unassigned field +class C +{ + public required readonly int Field; + public required int Prop1 { get; } +} +"); + + // PROTOTYPE(req): Confirm with LDM whether we want an error here. + comp.VerifyDiagnostics( + // (5,34): error CS9505: Required member 'C.Field' must be settable. + // public required readonly int Field; + Diagnostic(ErrorCode.ERR_RequiredMemberMustBeSettable, "Field").WithArguments("C.Field").WithLocation(5, 34), + // (6,25): error CS9505: Required member 'C.Prop1' must be settable. + // public required int Prop1 { get; } + Diagnostic(ErrorCode.ERR_RequiredMemberMustBeSettable, "Prop1").WithArguments("C.Prop1").WithLocation(6, 25) + ); + } + + [Fact] + public void ObsoleteMember() + { + var comp = CreateCompilationWithRequiredMembers(@" +using System; +#pragma warning disable CS0649 // Unassigned field +class C +{ + [Obsolete] + public required int Field; + [Obsolete] + public required int Prop1 { get; set; } +} +"); + + // PROTOTYPE(req): Confirm with LDM whether we want a warning here. + comp.VerifyDiagnostics(); + } + + [Fact] + public void ReadonlyPropertiesAndStructs() + { + var comp = CreateCompilationWithRequiredMembers(@" +readonly struct S1 +{ + public required readonly int Prop1 { get => 1; set {} } +} +struct S2 +{ + public readonly int Prop2 { get => 1; set {} } +} +struct S3 +{ + public int Prop2 { get => 1; readonly set {} } +} +"); + + comp.VerifyDiagnostics(); + } +} diff --git a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs index a4704092eb521..e7e6bd0a97824 100644 --- a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs +++ b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs @@ -1127,6 +1127,7 @@ internal ObsoleteAttributeData TryGetDeprecatedOrExperimentalOrObsoleteAttribute ObsoleteAttributeData obsoleteData = TryExtractObsoleteDataFromAttribute(info, decoder); switch (obsoleteData?.Message) { + // PROTOTYPE(req): Ignore required obsolete marker case ByRefLikeMarker when ignoreByRefLikeMarker: return null; } diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index 4dc73d5a53282..0cc374d095026 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -478,5 +478,6 @@ static AttributeDescription() internal static readonly AttributeDescription UnmanagedCallersOnlyAttribute = new AttributeDescription("System.Runtime.InteropServices", "UnmanagedCallersOnlyAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription InterpolatedStringHandlerAttribute = new AttributeDescription("System.Runtime.CompilerServices", "InterpolatedStringHandlerAttribute", s_signatures_HasThis_Void_Only); internal static readonly AttributeDescription InterpolatedStringHandlerArgumentAttribute = new AttributeDescription("System.Runtime.CompilerServices", "InterpolatedStringHandlerArgumentAttribute", s_signaturesOfInterpolatedStringArgumentAttribute); + internal static readonly AttributeDescription RequiredMemberAttribute = new AttributeDescription("System.Runtime.CompilerServices", "RequiredMemberAttribute", s_signatures_HasThis_Void_Only); } } diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index b8ce5205655ec..b43227dd5bd20 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -517,6 +517,8 @@ internal enum WellKnownMember System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear, + System_Runtime_CompilerServices_RequiredMemberAttribute__ctor, + Count // Remember to update the AllWellKnownTypeMembers tests when making changes here diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index 00f6ae1bcf8a4..74577d8c0ab6a 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3535,6 +3535,13 @@ static WellKnownMembers() 0, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_String, // Return Type + // System_Runtime_CompilerServices_RequiredMemberAttribute__ctor + (byte)MemberFlags.Constructor, // Flags + (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_RequiredMemberAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId + 0, // Arity + 0, // Method Signature + (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type + }; string[] allNames = new string[(int)WellKnownMember.Count] @@ -3979,6 +3986,7 @@ static WellKnownMembers() "Append", // System_Text_StringBuilder__AppendObject ".ctor", // System_Text_StringBuilder__ctor "ToStringAndClear", // System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear + ".ctor", // System_Runtime_CompilerServices_RequiredMemberAttribute__ctor }; s_descriptors = MemberDescriptor.InitializeFromStream(new System.IO.MemoryStream(initializationBytes, writable: false), allNames); diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs index 1ee9254677987..fd3366365333f 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -317,6 +317,8 @@ internal enum WellKnownType System_ArgumentNullException, + System_Runtime_CompilerServices_RequiredMemberAttribute, + NextAvailable, // Remember to update the AllWellKnownTypes tests when making changes here } @@ -625,6 +627,8 @@ internal static class WellKnownTypes "System.Text.StringBuilder", "System.Runtime.CompilerServices.DefaultInterpolatedStringHandler", "System.ArgumentNullException", + + "System.Runtime.CompilerServices.RequiredMemberAttribute" }; private static readonly Dictionary s_nameToTypeIdMap = new Dictionary((int)Count); diff --git a/src/Compilers/Test/Utilities/CSharp/NativeIntegerAttributesVisitor.cs b/src/Compilers/Test/Utilities/CSharp/NativeIntegerAttributesVisitor.cs index d0d3b72a54158..0dd6218087de6 100644 --- a/src/Compilers/Test/Utilities/CSharp/NativeIntegerAttributesVisitor.cs +++ b/src/Compilers/Test/Utilities/CSharp/NativeIntegerAttributesVisitor.cs @@ -2,11 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - -using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; using System.Text; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; @@ -16,7 +12,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities /// /// Returns a string with all symbols containing NativeIntegerAttributes. /// - internal sealed class NativeIntegerAttributesVisitor : CSharpSymbolVisitor + internal sealed class NativeIntegerAttributesVisitor : TestAttributesVisitor { internal static string GetString(PEModuleSymbol module) { @@ -26,109 +22,11 @@ internal static string GetString(PEModuleSymbol module) return builder.ToString(); } - private readonly StringBuilder _builder; - private readonly HashSet _reported; - - private NativeIntegerAttributesVisitor(StringBuilder builder) - { - _builder = builder; - _reported = new HashSet(); - } - - public override void DefaultVisit(Symbol symbol) - { - ReportSymbol(symbol); - } - - public override void VisitModule(ModuleSymbol module) + private NativeIntegerAttributesVisitor(StringBuilder builder) : base(builder) { - Visit(module.GlobalNamespace); - } - - public override void VisitNamespace(NamespaceSymbol @namespace) - { - VisitList(@namespace.GetMembers()); - } - - public override void VisitNamedType(NamedTypeSymbol type) - { - ReportSymbol(type); - VisitList(type.TypeParameters); - - foreach (var member in type.GetMembers()) - { - // Skip accessors since those are covered by associated symbol. - if (member.IsAccessor()) continue; - Visit(member); - } } - public override void VisitMethod(MethodSymbol method) - { - ReportSymbol(method); - VisitList(method.TypeParameters); - VisitList(method.Parameters); - } - - public override void VisitEvent(EventSymbol @event) - { - ReportSymbol(@event); - Visit(@event.AddMethod); - Visit(@event.RemoveMethod); - } - - public override void VisitProperty(PropertySymbol property) - { - ReportSymbol(property); - VisitList(property.Parameters); - Visit(property.GetMethod); - Visit(property.SetMethod); - } - - public override void VisitTypeParameter(TypeParameterSymbol typeParameter) - { - ReportSymbol(typeParameter); - } - - private void VisitList(ImmutableArray symbols) where TSymbol : Symbol - { - foreach (var symbol in symbols) - { - Visit(symbol); - } - } - - /// - /// Return the containing symbol used in the hierarchy here. Specifically, the - /// hierarchy contains types, members, and parameters only, and accessors are - /// considered members of the associated symbol rather than the type. - /// - private static Symbol GetContainingSymbol(Symbol symbol) - { - if (symbol.IsAccessor()) - { - return ((MethodSymbol)symbol).AssociatedSymbol; - } - var containingSymbol = symbol.ContainingSymbol; - return containingSymbol?.Kind == SymbolKind.Namespace ? null : containingSymbol; - } - - private static string GetIndentString(Symbol symbol) - { - int level = 0; - while (true) - { - symbol = GetContainingSymbol(symbol); - if (symbol is null) - { - break; - } - level++; - } - return new string(' ', level * 4); - } - - private static readonly SymbolDisplayFormat _displayFormat = SymbolDisplayFormat.TestFormatWithConstraints. + protected override SymbolDisplayFormat DisplayFormat => SymbolDisplayFormat.TestFormatWithConstraints. WithMemberOptions( SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeType | @@ -136,116 +34,9 @@ private static string GetIndentString(Symbol symbol) SymbolDisplayMemberOptions.IncludeExplicitInterface). WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.UseNativeIntegerUnderlyingType); - private void ReportContainingSymbols(Symbol symbol) - { - symbol = GetContainingSymbol(symbol); - if (symbol is null) - { - return; - } - if (_reported.Contains(symbol)) - { - return; - } - ReportContainingSymbols(symbol); - _builder.Append(GetIndentString(symbol)); - _builder.AppendLine(symbol.ToDisplayString(_displayFormat)); - _reported.Add(symbol); - } - - private void ReportSymbol(Symbol symbol) - { - var type = (symbol as TypeSymbol) ?? symbol.GetTypeOrReturnType().Type; - var attribute = GetNativeIntegerAttribute((symbol is MethodSymbol method) ? method.GetReturnTypeAttributes() : symbol.GetAttributes()); - Debug.Assert((type?.ContainsNativeInteger() != true) || (attribute != null)); - if (attribute == null) - { - return; - } - ReportContainingSymbols(symbol); - _builder.Append(GetIndentString(symbol)); - _builder.Append($"{ReportAttribute(attribute)} "); - _builder.AppendLine(symbol.ToDisplayString(_displayFormat)); - _reported.Add(symbol); - } - - private static Symbol GetAccessSymbol(Symbol symbol) - { - while (true) - { - switch (symbol.Kind) - { - case SymbolKind.Parameter: - case SymbolKind.TypeParameter: - symbol = symbol.ContainingSymbol; - break; - default: - return symbol; - } - } - } - - private static string ReportAttribute(CSharpAttributeData attribute) - { - var builder = new StringBuilder(); - builder.Append("["); - - var name = attribute.AttributeClass.Name; - if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length - 9); - builder.Append(name); - - var arguments = attribute.ConstructorArguments.ToImmutableArray(); - if (arguments.Length > 0) - { - builder.Append("("); - printValues(builder, arguments); - builder.Append(")"); - } - - builder.Append("]"); - return builder.ToString(); - - static void printValues(StringBuilder builder, ImmutableArray values) - { - for (int i = 0; i < values.Length; i++) - { - if (i > 0) - { - builder.Append(", "); - } - printValue(builder, values[i]); - } - } - - static void printValue(StringBuilder builder, TypedConstant value) - { - if (value.Kind == TypedConstantKind.Array) - { - builder.Append("{ "); - printValues(builder, value.Values); - builder.Append(" }"); - } - else - { - builder.Append(value.Value); - } - } - } + protected override bool TypeRequiresAttribute(TypeSymbol? type) => type?.ContainsNativeInteger() == true; - private static CSharpAttributeData GetNativeIntegerAttribute(ImmutableArray attributes) => + protected override CSharpAttributeData? GetTargetAttribute(ImmutableArray attributes) => GetAttribute(attributes, "System.Runtime.CompilerServices", "NativeIntegerAttribute"); - - private static CSharpAttributeData GetAttribute(ImmutableArray attributes, string namespaceName, string name) - { - foreach (var attribute in attributes) - { - var containingType = attribute.AttributeConstructor.ContainingType; - if (containingType.Name == name && containingType.ContainingNamespace.QualifiedName == namespaceName) - { - return attribute; - } - } - return null; - } } } diff --git a/src/Compilers/Test/Utilities/CSharp/NullableAttributesVisitor.cs b/src/Compilers/Test/Utilities/CSharp/NullableAttributesVisitor.cs index 04bc720e91fcb..cdae7795a3732 100644 --- a/src/Compilers/Test/Utilities/CSharp/NullableAttributesVisitor.cs +++ b/src/Compilers/Test/Utilities/CSharp/NullableAttributesVisitor.cs @@ -2,20 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - -using System.Collections.Generic; using System.Collections.Immutable; using System.Text; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities { /// /// Returns a string with all symbols containing nullable attributes. /// - internal sealed class NullableAttributesVisitor : CSharpSymbolVisitor + internal sealed class NullableAttributesVisitor : TestAttributesVisitor { internal static string GetString(PEModuleSymbol module) { @@ -26,30 +24,11 @@ internal static string GetString(PEModuleSymbol module) } private readonly PEModuleSymbol _module; - private readonly StringBuilder _builder; - private readonly HashSet _reported; - private CSharpAttributeData _nullableContext; + private CSharpAttributeData? _nullableContext; - private NullableAttributesVisitor(PEModuleSymbol module, StringBuilder builder) + private NullableAttributesVisitor(PEModuleSymbol module, StringBuilder builder) : base(builder) { _module = module; - _builder = builder; - _reported = new HashSet(); - } - - public override void DefaultVisit(Symbol symbol) - { - ReportSymbol(symbol); - } - - public override void VisitModule(ModuleSymbol module) - { - Visit(module.GlobalNamespace); - } - - public override void VisitNamespace(NamespaceSymbol @namespace) - { - VisitList(@namespace.GetMembers()); } public override void VisitNamedType(NamedTypeSymbol type) @@ -57,15 +36,7 @@ public override void VisitNamedType(NamedTypeSymbol type) var previousContext = _nullableContext; _nullableContext = GetNullableContextAttribute(type.GetAttributes()) ?? _nullableContext; - ReportSymbol(type); - VisitList(type.TypeParameters); - - foreach (var member in type.GetMembers()) - { - // Skip accessors since those are covered by associated symbol. - if (member.IsAccessor()) continue; - Visit(member); - } + base.VisitNamedType(type); _nullableContext = previousContext; } @@ -75,96 +46,19 @@ public override void VisitMethod(MethodSymbol method) var previousContext = _nullableContext; _nullableContext = GetNullableContextAttribute(method.GetAttributes()) ?? _nullableContext; - ReportSymbol(method); - VisitList(method.TypeParameters); - VisitList(method.Parameters); + base.VisitMethod(method); _nullableContext = previousContext; } - public override void VisitEvent(EventSymbol @event) - { - ReportSymbol(@event); - Visit(@event.AddMethod); - Visit(@event.RemoveMethod); - } - - public override void VisitProperty(PropertySymbol property) - { - ReportSymbol(property); - VisitList(property.Parameters); - Visit(property.GetMethod); - Visit(property.SetMethod); - } - - public override void VisitTypeParameter(TypeParameterSymbol typeParameter) - { - ReportSymbol(typeParameter); - } - - private void VisitList(ImmutableArray symbols) where TSymbol : Symbol - { - foreach (var symbol in symbols) - { - Visit(symbol); - } - } - - /// - /// Return the containing symbol used in the hierarchy here. Specifically, the - /// hierarchy contains types, members, and parameters only, and accessors are - /// considered members of the associated symbol rather than the type. - /// - private static Symbol GetContainingSymbol(Symbol symbol) - { - if (symbol.IsAccessor()) - { - return ((MethodSymbol)symbol).AssociatedSymbol; - } - var containingSymbol = symbol.ContainingSymbol; - return containingSymbol?.Kind == SymbolKind.Namespace ? null : containingSymbol; - } - - private static string GetIndentString(Symbol symbol) - { - int level = 0; - while (true) - { - symbol = GetContainingSymbol(symbol); - if (symbol is null) - { - break; - } - level++; - } - return new string(' ', level * 4); - } - - private static readonly SymbolDisplayFormat _displayFormat = SymbolDisplayFormat.TestFormatWithConstraints. + protected override SymbolDisplayFormat DisplayFormat => SymbolDisplayFormat.TestFormatWithConstraints. WithMemberOptions( SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeType | SymbolDisplayMemberOptions.IncludeRef | SymbolDisplayMemberOptions.IncludeExplicitInterface); - private void ReportContainingSymbols(Symbol symbol) - { - symbol = GetContainingSymbol(symbol); - if (symbol is null) - { - return; - } - if (_reported.Contains(symbol)) - { - return; - } - ReportContainingSymbols(symbol); - _builder.Append(GetIndentString(symbol)); - _builder.AppendLine(symbol.ToDisplayString(_displayFormat)); - _reported.Add(symbol); - } - - private void ReportSymbol(Symbol symbol) + protected override void ReportSymbol(Symbol symbol) { var nullableContextAttribute = GetNullableContextAttribute(symbol.GetAttributes()); var nullableAttribute = GetNullableAttribute((symbol is MethodSymbol method) ? method.GetReturnTypeAttributes() : symbol.GetAttributes()); @@ -196,7 +90,7 @@ private void ReportSymbol(Symbol symbol) _builder.Append($"{ReportAttribute(nullableAttribute)} "); } - _builder.AppendLine(symbol.ToDisplayString(_displayFormat)); + _builder.AppendLine(symbol.ToDisplayString(DisplayFormat)); _reported.Add(symbol); } @@ -216,70 +110,20 @@ private static Symbol GetAccessSymbol(Symbol symbol) } } - private static string ReportAttribute(CSharpAttributeData attribute) - { - var builder = new StringBuilder(); - builder.Append("["); - - var name = attribute.AttributeClass.Name; - if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length - 9); - builder.Append(name); - - var arguments = attribute.ConstructorArguments.ToImmutableArray(); - if (arguments.Length > 0) - { - builder.Append("("); - printValues(builder, arguments); - builder.Append(")"); - } - - builder.Append("]"); - return builder.ToString(); - - static void printValues(StringBuilder builder, ImmutableArray values) - { - for (int i = 0; i < values.Length; i++) - { - if (i > 0) - { - builder.Append(", "); - } - printValue(builder, values[i]); - } - } - - static void printValue(StringBuilder builder, TypedConstant value) - { - if (value.Kind == TypedConstantKind.Array) - { - builder.Append("{ "); - printValues(builder, value.Values); - builder.Append(" }"); - } - else - { - builder.Append(value.Value); - } - } - } - - private static CSharpAttributeData GetNullableContextAttribute(ImmutableArray attributes) => + private static CSharpAttributeData? GetNullableContextAttribute(ImmutableArray attributes) => GetAttribute(attributes, "System.Runtime.CompilerServices", "NullableContextAttribute"); - private static CSharpAttributeData GetNullableAttribute(ImmutableArray attributes) => + private static CSharpAttributeData? GetNullableAttribute(ImmutableArray attributes) => GetAttribute(attributes, "System.Runtime.CompilerServices", "NullableAttribute"); - private static CSharpAttributeData GetAttribute(ImmutableArray attributes, string namespaceName, string name) + protected override bool TypeRequiresAttribute(TypeSymbol? type) { - foreach (var attribute in attributes) - { - var containingType = attribute.AttributeConstructor.ContainingType; - if (containingType.Name == name && containingType.ContainingNamespace.QualifiedName == namespaceName) - { - return attribute; - } - } - return null; + throw ExceptionUtilities.Unreachable; + } + + protected override CSharpAttributeData GetTargetAttribute(ImmutableArray attributes) + { + throw ExceptionUtilities.Unreachable; } } } diff --git a/src/Compilers/Test/Utilities/CSharp/RequiredMemberAttributesVisitor.cs b/src/Compilers/Test/Utilities/CSharp/RequiredMemberAttributesVisitor.cs new file mode 100644 index 0000000000000..00c93aa972ba1 --- /dev/null +++ b/src/Compilers/Test/Utilities/CSharp/RequiredMemberAttributesVisitor.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text; +using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; + +namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities; + +internal class RequiredMemberAttributesVisitor : TestAttributesVisitor +{ + internal static string GetString(PEModuleSymbol module) + { + var builder = new StringBuilder(); + var visitor = new RequiredMemberAttributesVisitor(builder); + visitor.Visit(module); + return builder.ToString(); + } + + private RequiredMemberAttributesVisitor(StringBuilder builder) : base(builder) + { + } + + protected override SymbolDisplayFormat DisplayFormat => SymbolDisplayFormat.TestFormat; + + protected override CSharpAttributeData? GetTargetAttribute(ImmutableArray attributes) + => GetAttribute(attributes, "System.Runtime.CompilerServices", "RequiredMemberAttribute"); + + protected override bool TypeRequiresAttribute(TypeSymbol? type) + { + return false; + } +} diff --git a/src/Compilers/Test/Utilities/CSharp/TestAttributesVisitor.cs b/src/Compilers/Test/Utilities/CSharp/TestAttributesVisitor.cs new file mode 100644 index 0000000000000..d8308e85cae85 --- /dev/null +++ b/src/Compilers/Test/Utilities/CSharp/TestAttributesVisitor.cs @@ -0,0 +1,220 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Text; +using Microsoft.CodeAnalysis.CSharp.Symbols; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities +{ + internal abstract class TestAttributesVisitor : CSharpSymbolVisitor + { + protected readonly StringBuilder _builder; + protected readonly HashSet _reported; + + protected TestAttributesVisitor(StringBuilder builder) + { + _builder = builder; + _reported = new HashSet(); + } + + public override void DefaultVisit(Symbol symbol) + { + ReportSymbol(symbol); + } + + public override void VisitModule(ModuleSymbol module) + { + Visit(module.GlobalNamespace); + } + + public override void VisitNamespace(NamespaceSymbol @namespace) + { + VisitList(@namespace.GetMembers()); + } + + public override void VisitNamedType(NamedTypeSymbol type) + { + ReportSymbol(type); + VisitList(type.TypeParameters); + + foreach (var member in type.GetMembers()) + { + // Skip accessors since those are covered by associated symbol. + if (member.IsAccessor()) continue; + Visit(member); + } + } + + public override void VisitMethod(MethodSymbol method) + { + ReportSymbol(method); + VisitList(method.TypeParameters); + VisitList(method.Parameters); + } + + public override void VisitEvent(EventSymbol @event) + { + ReportSymbol(@event); + Visit(@event.AddMethod); + Visit(@event.RemoveMethod); + } + + public override void VisitProperty(PropertySymbol property) + { + ReportSymbol(property); + VisitList(property.Parameters); + Visit(property.GetMethod); + Visit(property.SetMethod); + } + + public override void VisitTypeParameter(TypeParameterSymbol typeParameter) + { + ReportSymbol(typeParameter); + } + + private void VisitList(ImmutableArray symbols) where TSymbol : Symbol + { + foreach (var symbol in symbols) + { + Visit(symbol); + } + } + + /// + /// Return the containing symbol used in the hierarchy here. Specifically, the + /// hierarchy contains types, members, and parameters only, and accessors are + /// considered members of the associated symbol rather than the type. + /// + private static Symbol? GetContainingSymbol(Symbol symbol) + { + if (symbol.IsAccessor()) + { + return ((MethodSymbol)symbol).AssociatedSymbol; + } + var containingSymbol = symbol.ContainingSymbol; + return containingSymbol?.Kind == SymbolKind.Namespace ? null : containingSymbol; + } + + protected static string GetIndentString(Symbol symbol) + { + int level = 0; + var current = symbol; + while (true) + { + current = GetContainingSymbol(current); + if (current is null) + { + break; + } + level++; + } + return new string(' ', level * 4); + } + + protected abstract SymbolDisplayFormat DisplayFormat { get; } + + protected void ReportContainingSymbols(Symbol symbol) + { + var s = GetContainingSymbol(symbol); + if (s is null) + { + return; + } + if (_reported.Contains(s)) + { + return; + } + ReportContainingSymbols(s); + _builder.Append(GetIndentString(s)); + _builder.AppendLine(s.ToDisplayString(DisplayFormat)); + _reported.Add(s); + } + + protected virtual void ReportSymbol(Symbol symbol) + { + var type = (symbol as TypeSymbol) ?? symbol.GetTypeOrReturnType().Type; + var attribute = GetTargetAttribute((symbol is MethodSymbol method) ? method.GetReturnTypeAttributes() : symbol.GetAttributes()); + Debug.Assert((!TypeRequiresAttribute(type)) || (attribute != null)); + if (attribute == null) + { + return; + } + ReportContainingSymbols(symbol); + _builder.Append(GetIndentString(symbol)); + _builder.Append($"{ReportAttribute(attribute)} "); + _builder.AppendLine(symbol.ToDisplayString(DisplayFormat)); + _reported.Add(symbol); + } + + protected static string ReportAttribute(CSharpAttributeData attribute) + { + var builder = new StringBuilder(); + builder.Append('['); + + Assert.NotNull(attribute.AttributeClass); + var name = attribute.AttributeClass!.Name; + if (name.EndsWith("Attribute")) name = name.Substring(0, name.Length - 9); + builder.Append(name); + + var arguments = attribute.ConstructorArguments.ToImmutableArray(); + if (arguments.Length > 0) + { + builder.Append('('); + printValues(builder, arguments); + builder.Append(')'); + } + + builder.Append(']'); + return builder.ToString(); + + static void printValues(StringBuilder builder, ImmutableArray values) + { + for (int i = 0; i < values.Length; i++) + { + if (i > 0) + { + builder.Append(", "); + } + printValue(builder, values[i]); + } + } + + static void printValue(StringBuilder builder, TypedConstant value) + { + if (value.Kind == TypedConstantKind.Array) + { + builder.Append("{ "); + printValues(builder, value.Values); + builder.Append(" }"); + } + else + { + builder.Append(value.Value); + } + } + } + + protected abstract bool TypeRequiresAttribute(TypeSymbol? type); + + protected abstract CSharpAttributeData? GetTargetAttribute(ImmutableArray attributes); + + protected static CSharpAttributeData? GetAttribute(ImmutableArray attributes, string namespaceName, string name) + { + foreach (var attribute in attributes) + { + Assert.NotNull(attribute.AttributeConstructor); + var containingType = attribute.AttributeConstructor!.ContainingType; + if (containingType.Name == name && containingType.ContainingNamespace.QualifiedName == namespaceName) + { + return attribute; + } + } + return null; + } + } +} diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index a8b6b5df00e13..4c32b28a689e8 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb @@ -544,7 +544,9 @@ End Namespace WellKnownType.System_Runtime_CompilerServices_SwitchExpressionException, WellKnownType.System_Runtime_CompilerServices_NativeIntegerAttribute, WellKnownType.System_Runtime_CompilerServices_IsExternalInit, - WellKnownType.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler + WellKnownType.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler, + WellKnownType.System_Runtime_CompilerServices_RequiredMemberAttribute + ' Not available on all platforms. Continue For Case WellKnownType.ExtSentinel @@ -610,7 +612,8 @@ End Namespace WellKnownType.System_Runtime_CompilerServices_SwitchExpressionException, WellKnownType.System_Runtime_CompilerServices_NativeIntegerAttribute, WellKnownType.System_Runtime_CompilerServices_IsExternalInit, - WellKnownType.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler + WellKnownType.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler, + WellKnownType.System_Runtime_CompilerServices_RequiredMemberAttribute ' Not available on all platforms. Continue For Case WellKnownType.ExtSentinel @@ -696,7 +699,8 @@ End Namespace WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__GetSubArray_T, WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor, WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags, - WellKnownMember.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear + WellKnownMember.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear, + WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor ' Not available yet, but will be in upcoming release. Continue For Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile, @@ -838,7 +842,8 @@ End Namespace WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__GetSubArray_T, WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor, WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags, - WellKnownMember.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear + WellKnownMember.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear, + WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor ' Not available yet, but will be in upcoming release. Continue For Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile, diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs index d04f935e73e1a..4619b76bdf234 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs @@ -159,6 +159,8 @@ public override bool IsVolatile get { return false; } } + internal override bool IsRequired => throw ExceptionUtilities.Unreachable; + public override FlowAnalysisAnnotations FlowAnalysisAnnotations { get { return FlowAnalysisAnnotations.None; } diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs index 69fa80e320486..1817d3ab43517 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs @@ -164,6 +164,8 @@ public override IEnumerable MemberNames get { throw ExceptionUtilities.Unreachable; } } + internal override bool HasDeclaredRequiredMembers => throw ExceptionUtilities.Unreachable; + public override ImmutableArray GetMembers() { return _methods.Cast();