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.
+
+ 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
+
+ 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 less visible or have a setter less visible than the containing type '{1}'.
+
+
+
+
+ Required member '{0}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ {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
+
+ 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.
+
+ 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
+
+ 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 less visible or have a setter less visible than the containing type '{1}'.
+
+
+
+
+ Required member '{0}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ {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
+
+ 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.
+
+ 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
+
+ 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 less visible or have a setter less visible than the containing type '{1}'.
+
+
+
+
+ Required member '{0}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ "{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
+
+ 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.
+
+ 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
+
+ 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 less visible or have a setter less visible than the containing type '{1}'.
+
+
+
+
+ Required member '{0}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ '{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
+
+ 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.
+
+ 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
+
+ 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 less visible or have a setter less visible than the containing type '{1}'.
+
+
+
+
+ Required member '{0}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ '{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
+
+ 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.
+
+ 指定された式を fixed ステートメントで使用することはできません
@@ -977,6 +982,11 @@
メソッド '{0}' は、型パラメーター '{1}' に対して 'default' 制約を指定していますが、オーバーライドされた、または明示的に実装されたメソッド '{3}' の対応する型パラメーター '{2}' は、参照型または値の型に制約されています。
+
+
+ '{0}': cannot remove 'required' from '{1}' when overriding
+
+ メソッド '{0}' は、型パラメーター '{1}' に対して 'class' 制約を指定していますが、オーバーライドされた、または明示的に実装されたメソッド '{3}' の対応する型パラメーター '{2}' は参照型ではありません。
@@ -1087,6 +1097,26 @@
リレーショナル パターンは、浮動小数点の NaN に使用することはできません。
+
+
+ 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}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ '{0}': ターゲットのランタイムはオーバーライドで covariant 型をサポートしていません。型は、オーバーライドされるメンバー '{1}' と一致する '{2}' にする必要があります
@@ -1382,6 +1412,11 @@
レコード構造体'record structs' is not localizable.
+
+
+ required members
+
+ レコードでシールされた 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.
+
+ fixed 문에서는 지정된 식을 사용할 수 없습니다.
@@ -977,6 +982,11 @@
메서드 '{0}'이(가) 형식 매개 변수 '{1}'의 'default' 제약 조건을 지정하지만 재정의되었거나 명시적으로 구현된 메서드 '{3}'의 해당 형식 매개 변수 '{2}'이(가) 참조 형식 또는 값 형식으로 제한됩니다.
+
+
+ '{0}': cannot remove 'required' from '{1}' when overriding
+
+ '{0}' 메서드는 형식 매개 변수 '{1}'의 'class' 제약 조건을 지정하지만 재정의되었거나 명시적으로 구현된 '{3}' 메서드의 해당 형식 매개 변수 '{2}'이(가) 참조 형식이 아닙니다.
@@ -1087,6 +1097,26 @@
부동 소수점 NaN에는 관계형 패턴을 사용할 수 없습니다.
+
+
+ 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}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ '{0}': 대상 런타임이 재정의에서 공변(covariant) 형식을 지원하지 않습니다. 재정의된 멤버 '{1}'과(와) 일치하려면 '{2}' 형식이어야 합니다.
@@ -1382,6 +1412,11 @@
레코드 구조체'record structs' is not localizable.
+
+
+ required members
+
+ 레코드의 봉인된 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.
+
+ 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
+
+ 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 less visible or have a setter less visible than the containing type '{1}'.
+
+
+
+
+ Required member '{0}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ „{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
+
+ 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.
+
+ 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
+
+ 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 less visible or have a setter less visible than the containing type '{1}'.
+
+
+
+
+ Required member '{0}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ '{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
+
+ 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.
+
+ Заданное выражение невозможно использовать в операторе fixed
@@ -977,6 +982,11 @@
Метод "{0}" задает ограничение "default" для параметра типа "{1}", но соответствующий параметр типа "{2}" переопределенного или явно реализованного метода "{3}" ограничен и может представлять собой только тип ссылки или тип значения.
+
+
+ '{0}': cannot remove 'required' from '{1}' when overriding
+
+ Метод "{0}" задает ограничение class для параметра типа "{1}", но соответствующий параметр типа "{2}" переопределенного или явно реализованного метода "{3}" не является ссылочным типом.
@@ -1087,6 +1097,26 @@
Реляционные шаблоны не могут использоваться для NaN с плавающей запятой.
+
+
+ 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}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ "{0}": целевая среда выполнения не поддерживает ковариантные типы в переопределениях. Для сопоставления переопределенного элемента "{1}" необходимо использовать тип "{2}".
@@ -1382,6 +1412,11 @@
структуры записей'record structs' is not localizable.
+
+
+ required members
+
+ запечатанный 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.
+
+ 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}' 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 less visible or have a setter less visible than the containing type '{1}'.
+
+
+
+
+ Required member '{0}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ '{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
+
+ 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.
+
+ 给定表达式不能用于 fixed 语句中
@@ -977,6 +982,11 @@
方法“{0}”为类型参数“{1}”指定了 "default" 约束,但被替代的或显式实现的方法“{3}”的对应类型参数“{2}” 仅限于引用类型或值类型。
+
+
+ '{0}': cannot remove 'required' from '{1}' when overriding
+
+ 方法 "{0}" 为类型参数 "{1}" 指定了 "class" 约束,但重写的或显式实现的方法 "{3}" 的对应类型参数 "{2}" 不是引用类型。
@@ -1087,6 +1097,26 @@
关系模式可能不能用于浮点 NaN。
+
+
+ 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}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ “{0}”: 目标运行时不支持替代中的协变类型。类型必须为“{2}”才能匹配替代成员“{1}”
@@ -1382,6 +1412,11 @@
记录结构'record structs' is not localizable.
+
+
+ required members
+
+ 记录的密封 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.
+
+ 指定運算式無法用於 fixed 陳述式中
@@ -977,6 +982,11 @@
方法 '{0}' 會為型別參數 '{1}' 指定 'default' 條件約束,但覆寫或明確實作方法 '{3}' 的對應型別參數 '{2}' 會限制為參考型別或實值型別。
+
+
+ '{0}': cannot remove 'required' from '{1}' when overriding
+
+ 方法 '{0}' 會為型別參數 '{1}' 指定 'class' 條件約束,但覆寫或明確實作的方法 '{3}' 對應型別參數 '{2}' 不屬於參考型別。
@@ -1087,6 +1097,26 @@
浮點 NaN 不可使用關聯性模式。
+
+
+ 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}' must be settable.
+
+
+
+
+ Types and aliases cannot be named 'required'.
+
+ '{0}': 在覆寫中,目標執行階段不支援 Covariant 類型。類型必須是 '{2}',才符合覆寫的成員 '{1}'
@@ -1382,6 +1412,11 @@
記錄結構'record structs' is not localizable.
+
+
+ required members
+
+ 記錄中有密封的 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();