From 723848411b4221f883d212bf52cc2e764247aa4e Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Tue, 21 Dec 2021 16:01:42 -0800 Subject: [PATCH 01/11] Report errors on invalid required declarations. --- .../CSharp/Portable/CSharpResources.resx | 6 + .../CSharp/Portable/Errors/ErrorCode.cs | 4 + .../Portable/Symbols/Source/ModifierUtils.cs | 13 +- .../Source/SourceMemberContainerSymbol.cs | 16 +- .../Symbols/Source/SourceMemberFieldSymbol.cs | 25 +- .../Symbols/Source/SourcePropertySymbol.cs | 12 + .../Portable/xlf/CSharpResources.cs.xlf | 10 + .../Portable/xlf/CSharpResources.de.xlf | 10 + .../Portable/xlf/CSharpResources.es.xlf | 10 + .../Portable/xlf/CSharpResources.fr.xlf | 10 + .../Portable/xlf/CSharpResources.it.xlf | 10 + .../Portable/xlf/CSharpResources.ja.xlf | 10 + .../Portable/xlf/CSharpResources.ko.xlf | 10 + .../Portable/xlf/CSharpResources.pl.xlf | 10 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 10 + .../Portable/xlf/CSharpResources.ru.xlf | 10 + .../Portable/xlf/CSharpResources.tr.xlf | 10 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 10 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 10 + .../Symbol/Symbols/RequiredMembersTests.cs | 284 ++++++++++++++++++ 20 files changed, 482 insertions(+), 8 deletions(-) create mode 100644 src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index a76b0e21f90aa..b613b98efd186 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6941,4 +6941,10 @@ 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 not be named 'required'. + + + required members + diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index c6ac42c8d647c..e40da273d7c5e 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2029,5 +2029,9 @@ 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, } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs index f28cdf1356928..ceb889a17f5fa 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); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index bf05a2b68cf19..57b687b710fae 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -449,14 +449,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 diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index b2b6cdf5584d1..1b560d0742d12 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -148,7 +148,8 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp DeclarationModifiers.Volatile | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | - DeclarationModifiers.Abstract; // filtered out later + DeclarationModifiers.Abstract | + DeclarationModifiers.Required; // filtered out later var errorLocation = new SourceLocation(firstIdentifier); DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers( @@ -186,7 +187,13 @@ 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) + { + // 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 +223,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/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/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 0c143f283af8f..b4d987d271105 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -1087,6 +1087,11 @@ Relační vzory se nedají použít pro hodnotu Není číslo s plovoucí desetinnou čárkou. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' {0}: Cílový modul runtime nepodporuje v přepisech kovariantní typy. Typ musí být {2}, aby odpovídal přepsanému členu {1}. @@ -1382,6 +1387,11 @@ struktury záznamů 'record structs' is not localizable. + + required members + required members + + sealed ToString in record zapečetěný ToString v záznamu diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 20f5cf9246ee6..a26a53dcb2ec7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1087,6 +1087,11 @@ Relationale Muster dürfen nicht für Gleitkomma-NaNs verwendet werden. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' {0}: Die Zielruntime unterstützt keine covarianten Typen in Überschreibungen. Der Typ muss "{2}" sein, um dem überschriebenen Member "{1}" zu entsprechen. @@ -1382,6 +1387,11 @@ Datensatzstrukturen 'record structs' is not localizable. + + required members + required members + + sealed ToString in record versiegelte "ToString" im Datensatz diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index e777231f2d8c5..e88006466b84a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1087,6 +1087,11 @@ No se pueden usar patrones relacionales para un valor NaN de punto flotante. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' "{0}": el entorno de ejecución de destino no admite los tipos de covariante en las invalidaciones. El tipo debe ser "{2}" para que coincida con el miembro "{1}" invalidado. @@ -1382,6 +1387,11 @@ registros 'record structs' is not localizable. + + required members + required members + + sealed ToString in record ToString sellado en el registro diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index a1ec5ce86a71e..0e30ae0ddea5d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1087,6 +1087,11 @@ Les modèles relationnels ne peuvent pas être utilisés pour une valeur NaN à virgule flottante. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}' : le runtime cible ne prend pas en charge les types covariants dans les substitutions. Le type doit être '{2}' pour correspondre au membre substitué '{1}' @@ -1382,6 +1387,11 @@ structs d’enregistrement 'record structs' is not localizable. + + required members + required members + + sealed ToString in record ToString scellé dans l’enregistrement diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 3099d6cfab162..a7835e3141be5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1087,6 +1087,11 @@ Non è possibile usare i criteri relazionali per un valore NaN a virgola mobile. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': il runtime di destinazione non supporta tipi covarianti negli override. Il tipo deve essere '{2}' in modo da corrispondere al membro '{1}' di cui è stato eseguito l'override @@ -1382,6 +1387,11 @@ struct di record 'record structs' is not localizable. + + required members + required members + + sealed ToString in record ToString sealed nel record diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 5ded70e499670..78ebd039843a8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1087,6 +1087,11 @@ リレーショナル パターンは、浮動小数点の NaN に使用することはできません。 + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': ターゲットのランタイムはオーバーライドで covariant 型をサポートしていません。型は、オーバーライドされるメンバー '{1}' と一致する '{2}' にする必要があります @@ -1382,6 +1387,11 @@ レコード構造体 'record structs' is not localizable. + + required members + required members + + sealed ToString in record レコードでシールされた ToString diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 0467b6f969aa3..d5fc12e260ebe 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1087,6 +1087,11 @@ 부동 소수점 NaN에는 관계형 패턴을 사용할 수 없습니다. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': 대상 런타임이 재정의에서 공변(covariant) 형식을 지원하지 않습니다. 재정의된 멤버 '{1}'과(와) 일치하려면 '{2}' 형식이어야 합니다. @@ -1382,6 +1387,11 @@ 레코드 구조체 'record structs' is not localizable. + + required members + required members + + sealed ToString in record 레코드의 봉인된 ToString diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 3d05f013a9aff..1dfe4133834b8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1087,6 +1087,11 @@ Wzorców relacyjnych nie można używać na potrzeby zmiennoprzecinkowej wartości NaN. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' „{0}”: docelowe środowisko uruchomieniowe nie obsługuje typów kowariantnych w przesłonięciach. Typem musi być „{2}”, aby zachować zgodność z przesłoniętą składową „{1}”. @@ -1382,6 +1387,11 @@ struktury rekordów 'record structs' is not localizable. + + required members + required members + + sealed ToString in record zapieczętowany obiekt ToString w rekordzie diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index be99a4c58d7cb..319272bc30954 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1087,6 +1087,11 @@ Os padrões relacionais não podem ser usados para um NaN de ponto flutuante. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': o runtime de destino não dá suporte a tipos covariantes em substituições. O tipo precisa ser '{2}' para corresponder ao membro substituído '{1}' @@ -1382,6 +1387,11 @@ registrar structs 'record structs' is not localizable. + + required members + required members + + sealed ToString in record ToString selado no registro diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index e385c0a76ab08..feec841b41ff3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1087,6 +1087,11 @@ Реляционные шаблоны не могут использоваться для NaN с плавающей запятой. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' "{0}": целевая среда выполнения не поддерживает ковариантные типы в переопределениях. Для сопоставления переопределенного элемента "{1}" необходимо использовать тип "{2}". @@ -1382,6 +1387,11 @@ структуры записей 'record structs' is not localizable. + + required members + required members + + sealed ToString in record запечатанный ToString в записи diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index da8185fac7dfd..9fe8487a4efa5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1087,6 +1087,11 @@ İlişkisel desenler, kayan noktalı NaN için kullanılamaz. + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': Hedef çalışma zamanı, geçersiz kılmalarda birlikte değişken türleri desteklemiyor. Tür, geçersiz kılınan '{1}' üyesiyle eşleşmek için '{2}' olmalıdır @@ -1382,6 +1387,11 @@ kayıt yapıları 'record structs' is not localizable. + + required members + required members + + sealed ToString in record kayıtta mühürlü ToString diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 9df925ab44fa9..5a48fd424489f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1087,6 +1087,11 @@ 关系模式可能不能用于浮点 NaN。 + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' “{0}”: 目标运行时不支持替代中的协变类型。类型必须为“{2}”才能匹配替代成员“{1}” @@ -1382,6 +1387,11 @@ 记录结构 'record structs' is not localizable. + + required members + required members + + sealed ToString in record 记录的密封 ToString diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index ae3bf3dadf94b..c05c909f7bc44 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1087,6 +1087,11 @@ 浮點 NaN 不可使用關聯性模式。 + + Types and aliases cannot not be named 'required'. + Types and aliases cannot not be named 'required'. + + '{0}': Target runtime doesn't support covariant types in overrides. Type must be '{2}' to match overridden member '{1}' '{0}': 在覆寫中,目標執行階段不支援 Covariant 類型。類型必須是 '{2}',才符合覆寫的成員 '{1}' @@ -1382,6 +1387,11 @@ 記錄結構 'record structs' is not localizable. + + required members + required members + + sealed ToString in record 記錄中有密封的 ToString 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..6744ec9e860fd --- /dev/null +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -0,0 +1,284 @@ +// 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 Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols; + +[CompilerTrait(CompilerFeature.RequiredMembers)] +public class RequiredMembersTests : CSharpTestBase +{ + [Fact] + public void InvalidModifierLocations() + { + var comp = CreateCompilation(@" +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 = CreateCompilation(@" +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() + { + var comp = CreateCompilation(@" +class C +{ + required int Field; + required int Prop { get; set; } +} +", parseOptions: TestOptions.Regular10); + + comp.VerifyDiagnostics( + // (4,18): error CS8652: The feature 'required members' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // required int Field; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Field").WithArguments("required members").WithLocation(4, 18), + // (4,18): warning CS0169: The field 'C.Field' is never used + // required int Field; + Diagnostic(ErrorCode.WRN_UnreferencedField, "Field").WithArguments("C.Field").WithLocation(4, 18), + // (5,18): error CS8652: The feature 'required members' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // required int Prop { get; set; } + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop").WithArguments("required members").WithLocation(5, 18) + ); + } + + [Fact] + public void DuplicateKeyword() + { + var comp = CreateCompilation(@" +class C +{ + required required int Field; + required required int Prop { get; set; } +} +"); + + comp.VerifyDiagnostics( + // (4,14): error CS1004: Duplicate 'required' modifier + // required required int Field; + Diagnostic(ErrorCode.ERR_DuplicateModifier, "required").WithArguments("required").WithLocation(4, 14), + // (4,27): warning CS0169: The field 'C.Field' is never used + // required required int Field; + Diagnostic(ErrorCode.WRN_UnreferencedField, "Field").WithArguments("C.Field").WithLocation(4, 27), + // (5,14): error CS1004: Duplicate 'required' modifier + // required required int Prop { get; set; } + Diagnostic(ErrorCode.ERR_DuplicateModifier, "required").WithArguments("required").WithLocation(5, 14) + ); + } + + [Theory] + [CombinatorialData] + public void InvalidNames(bool use10) + { + var comp = CreateCompilation(@" +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 {} +} +", parseOptions: use10 ? TestOptions.Regular10 : null); + + 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 not be named 'required'. + // struct required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(4, 12), + // (8,11): error CS9500: Types and aliases cannot not be named 'required'. + // class required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(8, 11), + // (12,15): error CS9500: Types and aliases cannot not be named 'required'. + // interface required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(12, 15), + // (16,19): error CS9500: Types and aliases cannot not be named 'required'. + // delegate void required(); + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(16, 19), + // (20,12): error CS9500: Types and aliases cannot not be named 'required'. + // record required(); + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(20, 12), + // (24,19): error CS9500: Types and aliases cannot not be named 'required'. + // record struct required(); + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(24, 19), + // (30,15): error CS9500: Types and aliases cannot not be named 'required'. + // class required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(30, 15), + // (35,11): error CS9500: Types and aliases cannot not be named 'required'. + // class required {} + Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(35, 11) + } + ); + } +} From e69a49e32a25b9b2cc66fc4c23cfc4615c3b9718 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Mon, 27 Dec 2021 17:41:31 -0800 Subject: [PATCH 02/11] Add support for emitting RequiredMembersAttribute in source Adding `required` to a member now results in the type having a `RequiredMembersAttribute` emitted with the name of that member as the contents. Reading this data from metadata is not yet supported, nor is adding the requisite `ObsoleteAttribute` to constructors that depend on such contracts. The rules for when required is allowed and when it is disallowed are documented in https://github.com/dotnet/csharplang/pull/5566, pending LDM review. Test plan: https://github.com/dotnet/roslyn/issues/57046 --- .../CSharp/Portable/CSharpResources.resx | 12 + .../CSharp/Portable/Errors/ErrorCode.cs | 4 + .../SynthesizedStateMachineProperty.cs | 2 + .../AnonymousType.FieldSymbol.cs | 2 + .../AnonymousType.PropertySymbol.cs | 2 + .../Portable/Symbols/ErrorPropertySymbol.cs | 2 + .../CSharp/Portable/Symbols/FieldSymbol.cs | 5 + .../Symbols/Metadata/PE/PEFieldSymbol.cs | 3 + .../Symbols/Metadata/PE/PEPropertySymbol.cs | 9 + .../CSharp/Portable/Symbols/PropertySymbol.cs | 5 + .../Symbols/SignatureOnlyPropertySymbol.cs | 2 + .../Portable/Symbols/Source/ModifierUtils.cs | 8 + .../Symbols/Source/SourceFieldSymbol.cs | 2 + .../Source/SourceMemberContainerSymbol.cs | 10 + ...berContainerSymbol_ImplementationChecks.cs | 17 + .../Symbols/Source/SourceNamedTypeSymbol.cs | 44 +- .../Source/SourcePropertySymbolBase.cs | 3 + .../CSharp/Portable/Symbols/Symbol.cs | 7 + .../Portable/Symbols/SymbolExtensions.cs | 7 + .../SynthesizedBackingFieldSymbol.cs | 2 + .../Synthesized/SynthesizedFieldSymbolBase.cs | 2 + .../Symbols/Wrapped/WrappedFieldSymbol.cs | 2 + .../Symbols/Wrapped/WrappedPropertySymbol.cs | 2 + .../Portable/xlf/CSharpResources.cs.xlf | 20 + .../Portable/xlf/CSharpResources.de.xlf | 20 + .../Portable/xlf/CSharpResources.es.xlf | 20 + .../Portable/xlf/CSharpResources.fr.xlf | 20 + .../Portable/xlf/CSharpResources.it.xlf | 20 + .../Portable/xlf/CSharpResources.ja.xlf | 20 + .../Portable/xlf/CSharpResources.ko.xlf | 20 + .../Portable/xlf/CSharpResources.pl.xlf | 20 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 20 + .../Portable/xlf/CSharpResources.ru.xlf | 20 + .../Portable/xlf/CSharpResources.tr.xlf | 20 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 20 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 20 + .../Symbol/Symbols/MissingSpecialMember.cs | 1 + .../Symbol/Symbols/RequiredMembersTests.cs | 850 +++++++++++++++++- .../Core/Portable/MetadataReader/PEModule.cs | 1 + .../Attributes/AttributeDescription.cs | 2 + .../Core/Portable/WellKnownMember.cs | 3 + .../Core/Portable/WellKnownMembers.cs | 17 + src/Compilers/Core/Portable/WellKnownTypes.cs | 4 + .../Test/Core/CompilationVerifier.cs | 2 +- .../Symbols/DisplayClassVariable.cs | 2 + 45 files changed, 1267 insertions(+), 29 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index b613b98efd186..efe21cbb9028b 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6947,4 +6947,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ 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 than the containing type '{1}'. + + + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index e40da273d7c5e..66c91cf9768c0 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2033,5 +2033,9 @@ internal enum ErrorCode // PROTOTYPE(req): Move above the comment and condense before merge ERR_RequiredNameDisallowed = 9500, + ERR_OverrideMustHaveRequired = 9501, + ERR_RequiredMembersCannotBeHidden = 9502, + ERR_RequiredMembersCannotBeLessVisibleThanContainingType = 9503, + ERR_ExplicitRequiredMembers = 9504, } } 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/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/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/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/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/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/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/ModifierUtils.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs index ceb889a17f5fa..c1bef4222d7c8 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs @@ -422,6 +422,14 @@ internal static CSDiagnosticInfo CheckAccessibility(DeclarationModifiers modifie } } + if ((modifiers & DeclarationModifiers.Required) != 0 + && symbol.Kind is SymbolKind.Property or SymbolKind.Field + && symbol.DeclaredAccessibility < symbol.ContainingType.DeclaredAccessibility) + { + // Required member '{0}' cannot be less visible than the containing type '{1}'. + return new CSDiagnosticInfo(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, symbol, symbol.ContainingType); + } + return null; } 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 57b687b710fae..7a9ccdb3fcf06 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -1619,6 +1619,7 @@ protected void AfterMembersChecks(BindingDiagnosticBag diagnostics) CheckSequentialOnPartialType(diagnostics); CheckForProtectedInStaticClass(diagnostics); CheckForUnmatchedOperators(diagnostics); + CheckForRequiredMembers(diagnostics); var location = Locations[0]; var compilation = DeclaringCompilation; @@ -2352,6 +2353,15 @@ private void CheckForEqualityAndGetHashCode(BindingDiagnosticBag diagnostics) } } + private void CheckForRequiredMembers(BindingDiagnosticBag diagnostics) + { + if (GetMembersUnordered().Any(SymbolExtensions.IsRequired)) + { + // Ensure that an error is reported if the required constructor isn't present. + _ = Binder.GetWellKnownTypeMember(DeclaringCompilation, WellKnownMember.System_Runtime_CompilerServices_RequiredMembersAttribute__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..60b8c61a80f20 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_RequiredMembersCannotBeHidden, 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, @@ -1409,6 +1420,12 @@ private static void CheckNonOverrideMember( diagnostics.Add(ErrorCode.WRN_NewOrOverrideExpected, hidingMemberLocation, hidingMember, hiddenMember); diagnosticAdded = true; } + else if (hiddenMember.IsRequired()) + { + // Required member '{0}' cannot be hidden by '{1}'. + diagnostics.Add(ErrorCode.ERR_RequiredMembersCannotBeHidden, hidingMemberLocation, hiddenMember, hidingMember); + diagnosticAdded = true; + } if (diagnosticAdded) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index cacbf6cb60e00..f654a111736ce 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,39 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r AddSynthesizedAttribute(ref attributes, this.DeclaringCompilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor)); } + + var requiredMembers = ArrayBuilder.GetInstance(); + foreach (var member in GetMembers()) + { + switch (member) + { + case SourceFieldSymbol { IsRequired: true }: + case SourcePropertySymbol { IsRequired: true, IsOverride: false }: + case SourcePropertySymbol { IsRequired: true, IsOverride: true, OverriddenProperty.IsRequired: false }: + requiredMembers.Add(member); + break; + } + } + + if (requiredMembers.Any()) + { + var stringType = compilation.GetSpecialType(SpecialType.System_String); + // Because GetMembers() is already sorted in lexical order, we don't need to do + // any additional sorting here. + var nameConstants = requiredMembers.SelectAsArray( + static (member, stringType) => new TypedConstant(stringType, TypedConstantKind.Primitive, member.Name), + stringType); + var stringArrayType = ArrayTypeSymbol.CreateSZArray(stringType.ContainingAssembly, TypeWithAnnotations.Create(stringType)); + + AddSynthesizedAttribute( + ref attributes, + compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_RequiredMembersAttribute__ctor, + ImmutableArray.Create(new TypedConstant(stringArrayType, nameConstants)))); + + // PROTOTYPE(req): Add obsolete marker to constructors if required members and Obsolete hasn't already been emitted + } + + requiredMembers.Free(); } #endregion diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs index 17df109569781..26379673a21e5 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; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs index 14d0714f477eb..6c07312f1a32f 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.RequiredMembersAttribute)) + { + // Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + diagnostics.Add(ErrorCode.ERR_ExplicitRequiredMembers, 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..e3229851e39d6 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs @@ -839,5 +839,12 @@ internal static bool HasAsyncMethodBuilderAttribute(this Symbol symbol, [NotNull builderArgument = null; return false; } + + internal static bool IsRequired(this Symbol symbol) + => symbol switch + { + FieldSymbol { IsRequired: true } or PropertySymbol { IsRequired: true } => true, + _ => false + }; } } 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/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..6bed480fef024 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 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..1d2064b7410e8 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 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 b4d987d271105..3839b2d3e896c 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Daný výraz nelze použít v příkazu fixed. @@ -977,6 +982,11 @@ Metoda {0} určuje omezení default pro parametr typu {1}, ale odpovídající parametr typu {2} přepsané nebo explicitně implementované metody {3} není omezený na typ odkazu nebo hodnoty. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Metoda {0} určuje omezení class pro parametr typu {1}, ale odpovídající parametr typu {2} přepsané nebo explicitně implementované metody {3} není odkazový typ. @@ -1087,6 +1097,16 @@ Relační vzory se nedají použít pro hodnotu Není číslo s plovoucí desetinnou čárkou. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index a26a53dcb2ec7..89783b8f2df85 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Der angegebene Ausdruck kann nicht in einer fixed-Anweisung verwendet werden. @@ -977,6 +982,11 @@ Die Methode "{0}" gibt eine default-Einschränkung für den Typparameter "{1}" an, aber der zugehörige Typparameter "{2}" der überschriebenen oder explizit implementierten Methode "{3}" ist auf einen Verweistyp oder einen Werttyp beschränkt. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Die Methode "{0}" gibt eine class-Einschränkung für den Typparameter "{1}" an, aber der zugehörige Typparameter "{2}" der außer Kraft gesetzten oder explizit implementierten Methode "{3}" ist kein Verweistyp. @@ -1087,6 +1097,16 @@ Relationale Muster dürfen nicht für Gleitkomma-NaNs verwendet werden. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index e88006466b84a..d2f3f7759ce34 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement La expresión proporcionada no se puede utilizar en una instrucción "fixed" @@ -977,6 +982,11 @@ El método "{0}" especifica una restricción "default" para el parámetro de tipo "{1}", pero el parámetro de tipo "{2}" correspondiente del método "{3}" invalidado o implementado explícitamente se restringe a un tipo de referencia o a un tipo de valor. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. El método "{0}" especifica una restricción "class" para el parámetro de tipo "{1}", pero el parámetro de tipo correspondiente "{2}" de los métodos invalidados o implementados explícitamente "{3}" no es un tipo de referencia. @@ -1087,6 +1097,16 @@ No se pueden usar patrones relacionales para un valor NaN de punto flotante. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 0e30ae0ddea5d..3a1922409a624 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Impossible d'utiliser l'expression donnée dans une instruction fixed @@ -977,6 +982,11 @@ La méthode '{0}' spécifie une contrainte 'default' pour le paramètre de type '{1}', mais le paramètre de type '{2}' correspondant de la méthode substituée ou explicitement implémentée '{3}' est limité à un type référence ou à un type valeur. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. La méthode '{0}' spécifie une contrainte 'class' pour le paramètre de type '{1}', mais le paramètre de type '{2}' correspondant de la méthode substituée ou explicitement implémentée '{3}' n'est pas un type référence. @@ -1087,6 +1097,16 @@ Les modèles relationnels ne peuvent pas être utilisés pour une valeur NaN à virgule flottante. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index a7835e3141be5..876d0de8aa0c2 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Non è possibile usare l'espressione specificata in un'istruzione fixed @@ -977,6 +982,11 @@ Il metodo '{0}' specifica un vincolo 'default' per il parametro di tipo '{1}', ma il parametro di tipo corrispondente '{2}' del metodo '{3}' sottoposto a override o implementato in modo esplicito è vincolato a un tipo riferimento a un tipo valore. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Il metodo '{0}' specifica un vincolo 'class' per il parametro di tipo '{1}', ma il parametro di tipo corrispondente '{2}' del metodo '{3}' sottoposto a override o implementato in modo esplicito non è un tipo riferimento. @@ -1087,6 +1097,16 @@ Non è possibile usare i criteri relazionali per un valore NaN a virgola mobile. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 78ebd039843a8..361d1431522a2 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement 指定された式を fixed ステートメントで使用することはできません @@ -977,6 +982,11 @@ メソッド '{0}' は、型パラメーター '{1}' に対して 'default' 制約を指定していますが、オーバーライドされた、または明示的に実装されたメソッド '{3}' の対応する型パラメーター '{2}' は、参照型または値の型に制約されています。 + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. メソッド '{0}' は、型パラメーター '{1}' に対して 'class' 制約を指定していますが、オーバーライドされた、または明示的に実装されたメソッド '{3}' の対応する型パラメーター '{2}' は参照型ではありません。 @@ -1087,6 +1097,16 @@ リレーショナル パターンは、浮動小数点の NaN に使用することはできません。 + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index d5fc12e260ebe..54db9f4a9cb80 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement fixed 문에서는 지정된 식을 사용할 수 없습니다. @@ -977,6 +982,11 @@ 메서드 '{0}'이(가) 형식 매개 변수 '{1}'의 'default' 제약 조건을 지정하지만 재정의되었거나 명시적으로 구현된 메서드 '{3}'의 해당 형식 매개 변수 '{2}'이(가) 참조 형식 또는 값 형식으로 제한됩니다. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. '{0}' 메서드는 형식 매개 변수 '{1}'의 'class' 제약 조건을 지정하지만 재정의되었거나 명시적으로 구현된 '{3}' 메서드의 해당 형식 매개 변수 '{2}'이(가) 참조 형식이 아닙니다. @@ -1087,6 +1097,16 @@ 부동 소수점 NaN에는 관계형 패턴을 사용할 수 없습니다. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 1dfe4133834b8..1df1eab7f5e08 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Podanego wyrażenia nie można użyć w instrukcji fixed @@ -977,6 +982,11 @@ Metoda „{0}” określa ograniczenie „default” dla parametru typu „{1}”, lecz odpowiadający parametr typu „{2}” przesłoniętej lub jawnie zaimplementowanej metody „{3}” jest ograniczony do typu odwołania lub typu wartości. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Metoda „{0}” określa ograniczenie „class” dla parametru typu „{1}”, lecz odpowiadający parametr typu „{2}” przesłoniętej lub jawnie zaimplementowanej metody „{3}” nie jest typem referencyjnym. @@ -1087,6 +1097,16 @@ Wzorców relacyjnych nie można używać na potrzeby zmiennoprzecinkowej wartości NaN. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 319272bc30954..2f1f82ade1a33 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement A expressão determinada não pode ser usada em uma instrução fixed @@ -977,6 +982,11 @@ O método '{0}' especifica uma restrição 'default' para o parâmetro de tipo '{1}', mas o parâmetro de tipo correspondente '{2}' do método substituído ou implementado explicitamente '{3}' está restrito por um tipo de referência ou um tipo de valor. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. O método '{0}' especifica uma restrição de 'class' para o parâmetro de tipo '{1}', mas o parâmetro de tipo correspondente '{2}' do método substituído ou implementado explicitamente '{3}' não é um tipo de referência. @@ -1087,6 +1097,16 @@ Os padrões relacionais não podem ser usados para um NaN de ponto flutuante. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index feec841b41ff3..3575f8940b137 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Заданное выражение невозможно использовать в операторе fixed @@ -977,6 +982,11 @@ Метод "{0}" задает ограничение "default" для параметра типа "{1}", но соответствующий параметр типа "{2}" переопределенного или явно реализованного метода "{3}" ограничен и может представлять собой только тип ссылки или тип значения. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. Метод "{0}" задает ограничение class для параметра типа "{1}", но соответствующий параметр типа "{2}" переопределенного или явно реализованного метода "{3}" не является ссылочным типом. @@ -1087,6 +1097,16 @@ Реляционные шаблоны не могут использоваться для NaN с плавающей запятой. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 9fe8487a4efa5..688141c10c389 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement Belirtilen ifade, fixed deyiminde kullanılamıyor @@ -977,6 +982,11 @@ '{0}' metodu, '{1}' tür parametresi için bir 'default' kısıtlaması belirtiyor, ancak geçersiz kılınan veya açıkça uygulanan '{3}' metodunun karşılık gelen '{2}' tür parametresi bir başvuru türü veya değer türüyle kısıtlanmış. + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. '{0}' yöntemi, '{1}' tür parametresi için bir 'class' kısıtlaması belirtiyor, ancak geçersiz kılınan veya açıkça uygulanan '{3}' yönteminin karşılık gelen '{2}' tür parametresi bir başvuru türü değil. @@ -1087,6 +1097,16 @@ İlişkisel desenler, kayan noktalı NaN için kullanılamaz. + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 5a48fd424489f..3d083e9066b9b 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement 给定表达式不能用于 fixed 语句中 @@ -977,6 +982,11 @@ 方法“{0}”为类型参数“{1}”指定了 "default" 约束,但被替代的或显式实现的方法“{3}”的对应类型参数“{2}” 仅限于引用类型或值类型。 + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. 方法 "{0}" 为类型参数 "{1}" 指定了 "class" 约束,但重写的或显式实现的方法 "{3}" 的对应类型参数 "{2}" 不是引用类型。 @@ -1087,6 +1097,16 @@ 关系模式可能不能用于浮点 NaN。 + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index c05c909f7bc44..0de23b5db9925 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.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + + The given expression cannot be used in a fixed statement 指定運算式無法用於 fixed 陳述式中 @@ -977,6 +982,11 @@ 方法 '{0}' 會為型別參數 '{1}' 指定 'default' 條件約束,但覆寫或明確實作方法 '{3}' 的對應型別參數 '{2}' 會限制為參考型別或實值型別。 + + '{0}': cannot remove 'required' from '{1}' when overriding + '{0}': cannot remove 'required' from '{1}' when overriding + + Method '{0}' specifies a 'class' constraint for type parameter '{1}', but corresponding type parameter '{2}' of overridden or explicitly implemented method '{3}' is not a reference type. 方法 '{0}' 會為型別參數 '{1}' 指定 'class' 條件約束,但覆寫或明確實作的方法 '{3}' 對應型別參數 '{2}' 不屬於參考型別。 @@ -1087,6 +1097,16 @@ 浮點 NaN 不可使用關聯性模式。 + + Required member '{0}' cannot be hidden by '{1}'. + Required member '{0}' cannot be hidden by '{1}'. + + + + Required member '{0}' cannot be less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible than the containing type '{1}'. + + Types and aliases cannot not be named 'required'. Types and aliases cannot not be named 'required'. diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index f1511be8f3a69..6876bb77c5da6 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_RequiredMembersAttribute: // Not yet in the platform. continue; case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation: diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs index 6744ec9e860fd..f3687d968b369 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -2,6 +2,8 @@ // 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.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Xunit; @@ -11,10 +13,42 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols; [CompilerTrait(CompilerFeature.RequiredMembers)] public class RequiredMembersTests : CSharpTestBase { + private const string RequiredMembersAttribute = @" +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] + public class RequiredMembersAttribute : Attribute + { + public RequiredMembersAttribute(params string[] members) + { + this.Members = members; + } + + public string[] Members { get; } + } +} +"; + + private CSharpCompilation CreateCompilationWithRequiredMembers(CSharpTestSource source, CSharpParseOptions? parseOptions = null, CSharpCompilationOptions? options = null) + => CreateCompilation(new[] { source, RequiredMembersAttribute }, options: options, parseOptions: parseOptions); + + private Action ValidateRequiredMembersInModule(string[] memberPaths) + { + return module => + { + 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()); + } + }; + } + [Fact] public void InvalidModifierLocations() { - var comp = CreateCompilation(@" + var comp = CreateCompilationWithRequiredMembers(@" required class C1 { required void M(required int i) @@ -104,7 +138,7 @@ class C2 : I2 [Fact] public void InvalidModifierCombinations() { - var comp = CreateCompilation(@" + var comp = CreateCompilationWithRequiredMembers(@" unsafe struct C { required const int F1 = 1; @@ -136,48 +170,48 @@ unsafe struct C [Fact] public void LangVersion() { - var comp = CreateCompilation(@" + var comp = CreateCompilationWithRequiredMembers(@" class C { - required int Field; - required int Prop { get; set; } + internal required int Field; + internal required int Prop { get; set; } } ", parseOptions: TestOptions.Regular10); comp.VerifyDiagnostics( - // (4,18): error CS8652: The feature 'required members' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. - // required int Field; - Diagnostic(ErrorCode.ERR_FeatureInPreview, "Field").WithArguments("required members").WithLocation(4, 18), - // (4,18): warning CS0169: The field 'C.Field' is never used - // required int Field; - Diagnostic(ErrorCode.WRN_UnreferencedField, "Field").WithArguments("C.Field").WithLocation(4, 18), - // (5,18): error CS8652: The feature 'required members' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. - // required int Prop { get; set; } - Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop").WithArguments("required members").WithLocation(5, 18) + // (4,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(4, 27), + // (4,27): warning CS0649: Field 'C.Field' is never assigned to, and will always have its default value 0 + // internal required int Field; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("C.Field", "0").WithLocation(4, 27), + // (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 Prop { get; set; } + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop").WithArguments("required members").WithLocation(5, 27) ); } [Fact] public void DuplicateKeyword() { - var comp = CreateCompilation(@" + var comp = CreateCompilationWithRequiredMembers(@" class C { - required required int Field; - required required int Prop { get; set; } + internal required required int Field; + internal required required int Prop { get; set; } } "); comp.VerifyDiagnostics( - // (4,14): error CS1004: Duplicate 'required' modifier - // required required int Field; - Diagnostic(ErrorCode.ERR_DuplicateModifier, "required").WithArguments("required").WithLocation(4, 14), - // (4,27): warning CS0169: The field 'C.Field' is never used - // required required int Field; - Diagnostic(ErrorCode.WRN_UnreferencedField, "Field").WithArguments("C.Field").WithLocation(4, 27), - // (5,14): error CS1004: Duplicate 'required' modifier - // required required int Prop { get; set; } - Diagnostic(ErrorCode.ERR_DuplicateModifier, "required").WithArguments("required").WithLocation(5, 14) + // (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) ); } @@ -185,7 +219,7 @@ class C [CombinatorialData] public void InvalidNames(bool use10) { - var comp = CreateCompilation(@" + var comp = CreateCompilationWithRequiredMembers(@" namespace N1 { struct required {} @@ -281,4 +315,766 @@ class required {} } ); } + + [Fact] + public void MissingRequiredMembersAttribute() + { + var comp = CreateCompilation(@" +class C +{ + public required int I { get; } +}"); + + // (2,7): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.RequiredMembersAttribute..ctor' + // class C + var expected = Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "C").WithArguments("System.Runtime.CompilerServices.RequiredMembersAttribute", ".ctor").WithLocation(2, 7); + comp.VerifyDiagnostics(expected); + comp.VerifyEmitDiagnostics(expected); + } + + [Fact] + public void MissingRequiredMembersAttributeCtor() + { + var comp = CreateCompilation(@" +class C +{ + public required int I { get; } +} + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] + public class RequiredMembersAttribute : Attribute + { + } +} +"); + + // (2,7): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.RequiredMembersAttribute..ctor' + // class C + var expected = Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "C").WithArguments("System.Runtime.CompilerServices.RequiredMembersAttribute", ".ctor").WithLocation(2, 7); + comp.VerifyDiagnostics(expected); + comp.VerifyEmitDiagnostics(expected); + } + + [Fact] + public void RequiredMembersAttributeEmitted() + { + var comp = CreateCompilationWithRequiredMembers(@" +class C +{ + public required int Prop { get; set; } + public required int Field; +} +"); + + var expectedRequiredMembers = new[] { "C.Prop", "C.Field" }; + + var verifier = CompileAndVerify(comp, sourceSymbolValidator: ValidateRequiredMembersInModule(expectedRequiredMembers)); + 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) + ); + + verifier.VerifyTypeIL("C", @" +.class private auto ansi beforefieldinit C + extends [netstandard]System.Object +{ + .custom instance void System.Runtime.CompilerServices.RequiredMembersAttribute::.ctor(string[]) = ( + 01 00 02 00 00 00 04 50 72 6f 70 05 46 69 65 6c + 64 00 00 + ) + // Fields + .field private int32 'k__BackingField' + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + .field public int32 Field + // Methods + .method public hidebysig specialname + instance int32 get_Prop () cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2050 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 C::'k__BackingField' + IL_0006: ret + } // end of method C::get_Prop + .method public hidebysig specialname + instance void set_Prop ( + int32 'value' + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2058 + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 C::'k__BackingField' + IL_0007: ret + } // end of method C::set_Prop + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x2061 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [netstandard]System.Object::.ctor() + IL_0006: ret + } // end of method C::.ctor + // Properties + .property instance int32 Prop() + { + .get instance int32 C::get_Prop() + .set instance void C::set_Prop(int32) + } +} // end of class C +"); + } + + [Fact] + public void RequiredMembersAttributeEmitted_OverrideRequiredProperty_MissingRequiredOnOverride() + { + var comp = CreateCompilationWithRequiredMembers(@" +class Base +{ + public virtual required int Prop { get; set; } +} +class Dervied : Base +{ + public override int Prop { get; set; } +} +"); + + comp.VerifyDiagnostics( + // (8,25): error CS9501: 'Dervied.Prop': cannot remove 'required' from 'Base.Prop' when overriding + // public override int Prop { get; set; } + Diagnostic(ErrorCode.ERR_OverrideMustHaveRequired, "Prop").WithArguments("Dervied.Prop", "Base.Prop").WithLocation(8, 25) + ); + } + + [Fact] + public void RequiredMembersAttributeEmitted_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 verifier = CompileAndVerify(comp, sourceSymbolValidator: ValidateRequiredMembersInModule(expectedRequiredMembers)); + verifier.VerifyDiagnostics(); + + verifier.VerifyTypeIL("Base", @" +.class private auto ansi beforefieldinit Base + extends [netstandard]System.Object +{ + .custom instance void System.Runtime.CompilerServices.RequiredMembersAttribute::.ctor(string[]) = ( + 01 00 01 00 00 00 04 50 72 6f 70 00 00 + ) + // Fields + .field private int32 'k__BackingField' + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Methods + .method public hidebysig specialname newslot virtual + instance int32 get_Prop () cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2050 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Base::'k__BackingField' + IL_0006: ret + } // end of method Base::get_Prop + .method public hidebysig specialname newslot virtual + instance void set_Prop ( + int32 'value' + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2058 + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 Base::'k__BackingField' + IL_0007: ret + } // end of method Base::set_Prop + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x2061 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [netstandard]System.Object::.ctor() + IL_0006: ret + } // end of method Base::.ctor + // Properties + .property instance int32 Prop() + { + .get instance int32 Base::get_Prop() + .set instance void Base::set_Prop(int32) + } +} // end of class Base +"); + + verifier.VerifyTypeIL("Derived", @" +.class private auto ansi beforefieldinit Derived + extends Base +{ + // Fields + .field private int32 'k__BackingField' + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Methods + .method public hidebysig specialname virtual + instance int32 get_Prop () cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2069 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Derived::'k__BackingField' + IL_0006: ret + } // end of method Derived::get_Prop + .method public hidebysig specialname virtual + instance void set_Prop ( + int32 'value' + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2071 + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 Derived::'k__BackingField' + IL_0007: ret + } // end of method Derived::set_Prop + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x207a + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void Base::.ctor() + IL_0006: ret + } // end of method Derived::.ctor + // Properties + .property instance int32 Prop() + { + .get instance int32 Derived::get_Prop() + .set instance void Derived::set_Prop(int32) + } +} // end of class Derived +"); + } + + [Fact] + public void RequiredMembersAttributeEmitted_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 verifier = CompileAndVerify(comp, sourceSymbolValidator: ValidateRequiredMembersInModule(expectedRequiredMembers)); + verifier.VerifyDiagnostics(); + + verifier.VerifyTypeIL("Base", @" +.class private auto ansi beforefieldinit Base + extends [netstandard]System.Object +{ + // Fields + .field private int32 'k__BackingField' + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Methods + .method public hidebysig specialname newslot virtual + instance int32 get_Prop () cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2050 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Base::'k__BackingField' + IL_0006: ret + } // end of method Base::get_Prop + .method public hidebysig specialname newslot virtual + instance void set_Prop ( + int32 'value' + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2058 + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 Base::'k__BackingField' + IL_0007: ret + } // end of method Base::set_Prop + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x2061 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [netstandard]System.Object::.ctor() + IL_0006: ret + } // end of method Base::.ctor + // Properties + .property instance int32 Prop() + { + .get instance int32 Base::get_Prop() + .set instance void Base::set_Prop(int32) + } +} // end of class Base +"); + + verifier.VerifyTypeIL("Derived", @" +.class private auto ansi beforefieldinit Derived + extends Base +{ + .custom instance void System.Runtime.CompilerServices.RequiredMembersAttribute::.ctor(string[]) = ( + 01 00 01 00 00 00 04 50 72 6f 70 00 00 + ) + // Fields + .field private int32 'k__BackingField' + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Methods + .method public hidebysig specialname virtual + instance int32 get_Prop () cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2069 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Derived::'k__BackingField' + IL_0006: ret + } // end of method Derived::get_Prop + .method public hidebysig specialname virtual + instance void set_Prop ( + int32 'value' + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2071 + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 Derived::'k__BackingField' + IL_0007: ret + } // end of method Derived::set_Prop + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x207a + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void Base::.ctor() + IL_0006: ret + } // end of method Derived::.ctor + // Properties + .property instance int32 Prop() + { + .get instance int32 Derived::get_Prop() + .set instance void Derived::set_Prop(int32) + } +} // end of class Derived +"); + + verifier.VerifyTypeIL("DerivedDerived", @" +.class private auto ansi beforefieldinit DerivedDerived + extends Derived +{ + // Fields + .field private int32 'k__BackingField' + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Methods + .method public hidebysig specialname virtual + instance int32 get_Prop () cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2082 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 DerivedDerived::'k__BackingField' + IL_0006: ret + } // end of method DerivedDerived::get_Prop + .method public hidebysig specialname virtual + instance void set_Prop ( + int32 'value' + ) cil managed + { + .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x208a + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 DerivedDerived::'k__BackingField' + IL_0007: ret + } // end of method DerivedDerived::set_Prop + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x2093 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void Derived::.ctor() + IL_0006: ret + } // end of method DerivedDerived::.ctor + // Properties + .property instance int32 Prop() + { + .get instance int32 DerivedDerived::get_Prop() + .set instance void DerivedDerived::set_Prop(int32) + } +} // end of class DerivedDerived +"); + } + + [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 +} +"); + + comp.VerifyDiagnostics( + // (10,20): error CS9502: Required member 'Base.Field' cannot be hidden by 'Derived1.Field'. + // public new int Field; // 1 + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeHidden, "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_RequiredMembersCannotBeHidden, "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_RequiredMembersCannotBeHidden, "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_RequiredMembersCannotBeHidden, "Field").WithArguments("Base.Field", "Derived2.Field").WithLocation(16, 20) + ); + } + + [Fact] + public void RequiredMembersMustBeAsVisibleAsContainingType() + { + var comp = CreateCompilationWithRequiredMembers(@" +#pragma warning disable CS0649 // Never assigned +#pragma warning disable CS0169 // Never used +public class C1 +{ + public required int Prop1 { get; set; } + internal protected required int Prop2 { get; set; } + internal required int Prop3 { get; set; } + protected required int Prop4 { get; set; } + private protected required int Prop5 { get; set; } + private required int Prop6 { get; set; } + public required int Field1; + internal protected required int Field2; + internal required int Field3; + protected required int Field4; + private protected required int Field5; + private required int Field6; +} +internal class C2 +{ + public required int Prop1 { get; set; } + internal protected required int Prop2 { get; set; } + internal required int Prop3 { get; set; } + protected required int Prop4 { get; set; } + private protected required int Prop5 { get; set; } + private required int Prop6 { get; set; } + public required int Field1; + internal protected required int Field2; + internal required int Field3; + protected required int Field4; + private protected required int Field5; + private required int Field6; +} +internal class Outer +{ + protected internal class C3 + { + public required int Prop1 { get; set; } + internal required int Prop2 { get; set; } + internal protected required int Prop3 { get; set; } + protected required int Prop4 { get; set; } + private protected required int Prop5 { get; set; } + private required int Prop6 { get; set; } + public required int Field1; + internal required int Field2; + internal protected required int Field3; + protected required int Field4; + private protected required int Field5; + private required int Field6; + } + protected class C4 + { + public required int Prop1 { get; set; } + internal protected required int Prop2 { get; set; } + internal required int Prop3 { get; set; } + protected required int Prop4 { get; set; } + private protected required int Prop5 { get; set; } + private required int Prop6 { get; set; } + public required int Field1; + internal protected required int Field2; + internal required int Field3; + protected required int Field4; + private protected required int Field5; + private required int Field6; + } + private protected class C5 + { + public required int Prop1 { get; set; } + internal protected required int Prop2 { get; set; } + internal required int Prop3 { get; set; } + protected required int Prop4 { get; set; } + private protected required int Prop5 { get; set; } + private required int Prop6 { get; set; } + public required int Field1; + internal protected required int Field2; + internal required int Field3; + protected required int Field4; + private protected required int Field5; + private required int Field6; + } + private class C6 + { + public required int Prop1 { get; set; } + internal protected required int Prop2 { get; set; } + internal required int Prop3 { get; set; } + protected required int Prop4 { get; set; } + private protected required int Prop5 { get; set; } + private required int Prop6 { get; set; } + public required int Field1; + internal protected required int Field2; + internal required int Field3; + protected required int Field4; + private protected required int Field5; + private required int Field6; + } +} +"); + + comp.VerifyDiagnostics( + // (7,37): error CS9503: Required member 'C1.Prop2' cannot be less visible than the containing type 'C1'. + // internal protected required int Prop2 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop2").WithArguments("C1.Prop2", "C1").WithLocation(7, 37), + // (8,27): error CS9503: Required member 'C1.Prop3' cannot be less visible than the containing type 'C1'. + // internal required int Prop3 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop3").WithArguments("C1.Prop3", "C1").WithLocation(8, 27), + // (9,28): error CS9503: Required member 'C1.Prop4' cannot be less visible than the containing type 'C1'. + // protected required int Prop4 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop4").WithArguments("C1.Prop4", "C1").WithLocation(9, 28), + // (10,36): error CS9503: Required member 'C1.Prop5' cannot be less visible than the containing type 'C1'. + // private protected required int Prop5 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop5").WithArguments("C1.Prop5", "C1").WithLocation(10, 36), + // (11,26): error CS9503: Required member 'C1.Prop6' cannot be less visible than the containing type 'C1'. + // private required int Prop6 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("C1.Prop6", "C1").WithLocation(11, 26), + // (13,37): error CS9503: Required member 'C1.Field2' cannot be less visible than the containing type 'C1'. + // internal protected required int Field2; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field2").WithArguments("C1.Field2", "C1").WithLocation(13, 37), + // (14,27): error CS9503: Required member 'C1.Field3' cannot be less visible than the containing type 'C1'. + // internal required int Field3; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field3").WithArguments("C1.Field3", "C1").WithLocation(14, 27), + // (15,28): error CS9503: Required member 'C1.Field4' cannot be less visible than the containing type 'C1'. + // protected required int Field4; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field4").WithArguments("C1.Field4", "C1").WithLocation(15, 28), + // (16,36): error CS9503: Required member 'C1.Field5' cannot be less visible than the containing type 'C1'. + // private protected required int Field5; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field5").WithArguments("C1.Field5", "C1").WithLocation(16, 36), + // (17,26): error CS9503: Required member 'C1.Field6' cannot be less visible than the containing type 'C1'. + // private required int Field6; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("C1.Field6", "C1").WithLocation(17, 26), + // (24,28): error CS9503: Required member 'C2.Prop4' cannot be less visible than the containing type 'C2'. + // protected required int Prop4 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop4").WithArguments("C2.Prop4", "C2").WithLocation(24, 28), + // (25,36): error CS9503: Required member 'C2.Prop5' cannot be less visible than the containing type 'C2'. + // private protected required int Prop5 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop5").WithArguments("C2.Prop5", "C2").WithLocation(25, 36), + // (26,26): error CS9503: Required member 'C2.Prop6' cannot be less visible than the containing type 'C2'. + // private required int Prop6 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("C2.Prop6", "C2").WithLocation(26, 26), + // (30,28): error CS9503: Required member 'C2.Field4' cannot be less visible than the containing type 'C2'. + // protected required int Field4; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field4").WithArguments("C2.Field4", "C2").WithLocation(30, 28), + // (31,36): error CS9503: Required member 'C2.Field5' cannot be less visible than the containing type 'C2'. + // private protected required int Field5; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field5").WithArguments("C2.Field5", "C2").WithLocation(31, 36), + // (32,26): error CS9503: Required member 'C2.Field6' cannot be less visible than the containing type 'C2'. + // private required int Field6; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("C2.Field6", "C2").WithLocation(32, 26), + // (39,31): error CS9503: Required member 'Outer.C3.Prop2' cannot be less visible than the containing type 'Outer.C3'. + // internal required int Prop2 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop2").WithArguments("Outer.C3.Prop2", "Outer.C3").WithLocation(39, 31), + // (41,32): error CS9503: Required member 'Outer.C3.Prop4' cannot be less visible than the containing type 'Outer.C3'. + // protected required int Prop4 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop4").WithArguments("Outer.C3.Prop4", "Outer.C3").WithLocation(41, 32), + // (42,40): error CS9503: Required member 'Outer.C3.Prop5' cannot be less visible than the containing type 'Outer.C3'. + // private protected required int Prop5 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop5").WithArguments("Outer.C3.Prop5", "Outer.C3").WithLocation(42, 40), + // (43,30): error CS9503: Required member 'Outer.C3.Prop6' cannot be less visible than the containing type 'Outer.C3'. + // private required int Prop6 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("Outer.C3.Prop6", "Outer.C3").WithLocation(43, 30), + // (45,31): error CS9503: Required member 'Outer.C3.Field2' cannot be less visible than the containing type 'Outer.C3'. + // internal required int Field2; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field2").WithArguments("Outer.C3.Field2", "Outer.C3").WithLocation(45, 31), + // (47,32): error CS9503: Required member 'Outer.C3.Field4' cannot be less visible than the containing type 'Outer.C3'. + // protected required int Field4; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field4").WithArguments("Outer.C3.Field4", "Outer.C3").WithLocation(47, 32), + // (48,40): error CS9503: Required member 'Outer.C3.Field5' cannot be less visible than the containing type 'Outer.C3'. + // private protected required int Field5; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field5").WithArguments("Outer.C3.Field5", "Outer.C3").WithLocation(48, 40), + // (49,30): error CS9503: Required member 'Outer.C3.Field6' cannot be less visible than the containing type 'Outer.C3'. + // private required int Field6; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("Outer.C3.Field6", "Outer.C3").WithLocation(49, 30), + // (57,40): error CS9503: Required member 'Outer.C4.Prop5' cannot be less visible than the containing type 'Outer.C4'. + // private protected required int Prop5 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop5").WithArguments("Outer.C4.Prop5", "Outer.C4").WithLocation(57, 40), + // (58,30): error CS9503: Required member 'Outer.C4.Prop6' cannot be less visible than the containing type 'Outer.C4'. + // private required int Prop6 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("Outer.C4.Prop6", "Outer.C4").WithLocation(58, 30), + // (63,40): error CS9503: Required member 'Outer.C4.Field5' cannot be less visible than the containing type 'Outer.C4'. + // private protected required int Field5; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field5").WithArguments("Outer.C4.Field5", "Outer.C4").WithLocation(63, 40), + // (64,30): error CS9503: Required member 'Outer.C4.Field6' cannot be less visible than the containing type 'Outer.C4'. + // private required int Field6; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("Outer.C4.Field6", "Outer.C4").WithLocation(64, 30), + // (73,30): error CS9503: Required member 'Outer.C5.Prop6' cannot be less visible than the containing type 'Outer.C5'. + // private required int Prop6 { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("Outer.C5.Prop6", "Outer.C5").WithLocation(73, 30), + // (79,30): error CS9503: Required member 'Outer.C5.Field6' cannot be less visible than the containing type 'Outer.C5'. + // private required int Field6; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("Outer.C5.Field6", "Outer.C5").WithLocation(79, 30) + ); + } + + [Fact] + public void RequiredMembersCannotBeExplicitInterfaceImplementations() + { + var comp = CreateCompilationWithRequiredMembers(@" +interface I +{ + int Prop { get; set; } +} +class C : I +{ + required int I.Prop { get; set; } +} +"); + + comp.VerifyDiagnostics( + // (8,20): error CS0106: The modifier 'required' is not valid for this item + // required int I.Prop { get; set; } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "Prop").WithArguments("required").WithLocation(8, 20) + ); + } + + [Fact] + public void UsingRequiredMembersAttributeExplicitly() + { + var comp = CreateCompilationWithRequiredMembers(@" +using System.Runtime.CompilerServices; +[RequiredMembers(new[] { ""Prop"" })] +class C +{ + public int Prop { get; set; } +} +"); + + comp.VerifyDiagnostics( + // (3,2): error CS9504: Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + // [RequiredMembers(new[] { "Prop" })] + Diagnostic(ErrorCode.ERR_ExplicitRequiredMembers, @"RequiredMembers(new[] { ""Prop"" })").WithLocation(3, 2) + ); + + var prop = comp.SourceModule.GlobalNamespace.GetMember("C.Prop"); + Assert.False(prop.IsRequired); + } } 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..292669e9d8219 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -199,6 +199,7 @@ static AttributeDescription() private static readonly byte[][] s_signatures_HasThis_Void_Only = { s_signature_HasThis_Void }; private static readonly byte[][] s_signatures_HasThis_Void_String_Only = { s_signature_HasThis_Void_String }; + private static readonly byte[][] s_signatures_HasThis_Void_SzArray_String_Only = { s_signature_HasThis_Void_SzArray_String }; private static readonly byte[][] s_signatures_HasThis_Void_Type_Only = { s_signature_HasThis_Void_Type }; private static readonly byte[][] s_signatures_HasThis_Void_Boolean_Only = { s_signature_HasThis_Void_Boolean }; @@ -478,5 +479,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 RequiredMembersAttribute = new AttributeDescription("System.Runtime.CompilerServices", "RequiredMembersAttribute", s_signatures_HasThis_Void_SzArray_String_Only); } } diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index b8ce5205655ec..b17789a712872 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -517,6 +517,9 @@ internal enum WellKnownMember System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear, + System_Runtime_CompilerServices_RequiredMembersAttribute__ctor, + System_Runtime_CompilerServices_RequiredMembersAttribute__get_Members, + 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..b2f9570027bf1 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3535,6 +3535,21 @@ static WellKnownMembers() 0, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_String, // Return Type + // System_Runtime_CompilerServices_RequiredMembersAttribute__ctor + (byte)MemberFlags.Constructor, // Flags + (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_RequiredMembersAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId + 0, // Arity + 1, // Method Signature + (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type + (byte)SignatureTypeCode.SZArray, (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_String, + + // System_Runtime_CompilerServices_RequiredMembersAttribute__get_Members + (byte)(MemberFlags.PropertyGet | MemberFlags.Static), // Flags + (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_RequiredMembersAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId + 0, // Arity + 0, // Method Signature + (byte)SignatureTypeCode.SZArray, (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Collections_Generic_EqualityComparer_T,// Return Type + }; string[] allNames = new string[(int)WellKnownMember.Count] @@ -3979,6 +3994,8 @@ static WellKnownMembers() "Append", // System_Text_StringBuilder__AppendObject ".ctor", // System_Text_StringBuilder__ctor "ToStringAndClear", // System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear + ".ctor", // System_Runtime_CompilerServices_RequiredMembersAttribute__ctor + "get_Members", // System_Runtime_CompilerServices_RequiredMembersAttribute__get_Members }; 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..5962d69453a08 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_RequiredMembersAttribute, + 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.RequiredMembersAttribute" }; private static readonly Dictionary s_nameToTypeIdMap = new Dictionary((int)Count); diff --git a/src/Compilers/Test/Core/CompilationVerifier.cs b/src/Compilers/Test/Core/CompilationVerifier.cs index 1ed62d8b828c8..a23902e55a141 100644 --- a/src/Compilers/Test/Core/CompilationVerifier.cs +++ b/src/Compilers/Test/Core/CompilationVerifier.cs @@ -193,7 +193,7 @@ public void VerifyTypeIL(string typeName, string expected) Assert.True(found, "Could not find type named " + typeName); } } - AssertEx.AssertEqualToleratingWhitespaceDifferences(expected, output.ToString(), escapeQuotes: false); + AssertEx.AssertEqualToleratingWhitespaceDifferences(expected, output.ToString().Replace("\t", " "), escapeQuotes: false); } public void Emit(string expectedOutput, int? expectedReturnCode, string[] args, IEnumerable manifestResources, EmitOptions emitOptions, Verification peVerify, SignatureDescription[] expectedSignatures) diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs index d04f935e73e1a..a175df54f20b1 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; } } + public override bool IsRequired => throw ExceptionUtilities.Unreachable; + public override FlowAnalysisAnnotations FlowAnalysisAnnotations { get { return FlowAnalysisAnnotations.None; } From cd5c7279f181f89260c08a161c2c300beb4b4a3c Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Wed, 26 Jan 2022 15:34:12 -0800 Subject: [PATCH 03/11] Update implementation with LDM decisions around metadata shape. --- ...ymousManager.TypeOrDelegatePublicSymbol.cs | 2 + .../AnonymousType.TemplateSymbol.cs | 2 + .../Portable/Symbols/ConstraintsHelper.cs | 3 + .../Portable/Symbols/ErrorTypeSymbol.cs | 2 + .../Symbols/Metadata/PE/PENamedTypeSymbol.cs | 3 + .../Portable/Symbols/NamedTypeSymbol.cs | 5 + .../Symbols/NativeIntegerTypeSymbol.cs | 2 + .../Retargeting/RetargetingNamedTypeSymbol.cs | 2 + .../FieldSymbolWithAttributesAndModifiers.cs | 9 +- .../Symbols/Source/SourceConstructorSymbol.cs | 3 + .../Source/SourceMemberContainerSymbol.cs | 50 +++++++++- .../Symbols/Source/SourceMemberFieldSymbol.cs | 8 ++ .../Symbols/Source/SourceNamedTypeSymbol.cs | 30 +----- .../Source/SourcePropertySymbolBase.cs | 16 +++- .../Symbols/SubstitutedNamedTypeSymbol.cs | 2 + .../CSharp/Portable/Symbols/Symbol.cs | 2 +- .../Synthesized/SynthesizedContainer.cs | 2 + .../SynthesizedEmbeddedAttributeSymbol.cs | 2 + .../Symbol/Symbols/MissingSpecialMember.cs | 2 +- .../Symbol/Symbols/MockNamedTypeSymbol.cs | 2 + .../Symbol/Symbols/RequiredMembersTests.cs | 93 +++++++++++++------ .../Attributes/AttributeDescription.cs | 2 +- .../Core/Portable/WellKnownMember.cs | 3 +- .../Core/Portable/WellKnownMembers.cs | 15 +-- src/Compilers/Core/Portable/WellKnownTypes.cs | 4 +- 25 files changed, 182 insertions(+), 84 deletions(-) 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..acb5904811b69 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; } } + public override bool HasDeclaredRequiredMembers => false; + public sealed override ImmutableArray GetTypeMembers() { return ImmutableArray.Empty; 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..602b689bcb719 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) } } + public 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/ErrorTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs index fdb77ade632e6..665f92169e6a7 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 } } + public override sealed bool HasDeclaredRequiredMembers => false; + /// /// Get all the members of this symbol. /// diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index df6df4a607427..15e273c4591fe 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 + public override bool HasDeclaredRequiredMembers => false; + public override ImmutableArray GetMembers() { EnsureAllMembersAreLoaded(); diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index f3b25e788f511..6338542a2841e 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. + /// + public 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..bd86f40c2b745 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); + public 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/Retargeting/RetargetingNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs index 4bd11b5db2f26..a131488cb034f 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 } } + public override bool HasDeclaredRequiredMembers => _underlyingType.HasDeclaredRequiredMembers; + public override ImmutableArray GetMembers() { return this.RetargetingTranslator.Retarget(_underlyingType.GetMembers()); 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/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/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index 7a9ccdb3fcf06..93fab0306e1da 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 = @@ -1301,6 +1326,21 @@ private void CheckMemberNameDistinctFromType(Symbol member, BindingDiagnosticBag } } + public override bool HasDeclaredRequiredMembers + { + get + { + if (_flags.TryGetHasDeclaredRequiredMembers(out bool hasDeclaredMembers)) + { + return hasDeclaredMembers; + } + + hasDeclaredMembers = GetMembersUnordered().Any(SymbolExtensions.IsRequired); + _flags.SetHasDeclaredRequiredMembers(hasDeclaredMembers); + return hasDeclaredMembers; + } + } + internal override ImmutableArray GetMembersUnordered() { var result = _lazyMembersFlattened; @@ -1619,7 +1659,7 @@ protected void AfterMembersChecks(BindingDiagnosticBag diagnostics) CheckSequentialOnPartialType(diagnostics); CheckForProtectedInStaticClass(diagnostics); CheckForUnmatchedOperators(diagnostics); - CheckForRequiredMembers(diagnostics); + CheckForRequiredMemberAttribute(diagnostics); var location = Locations[0]; var compilation = DeclaringCompilation; @@ -2353,12 +2393,12 @@ private void CheckForEqualityAndGetHashCode(BindingDiagnosticBag diagnostics) } } - private void CheckForRequiredMembers(BindingDiagnosticBag diagnostics) + private void CheckForRequiredMemberAttribute(BindingDiagnosticBag diagnostics) { - if (GetMembersUnordered().Any(SymbolExtensions.IsRequired)) + if (HasDeclaredRequiredMembers) { // Ensure that an error is reported if the required constructor isn't present. - _ = Binder.GetWellKnownTypeMember(DeclaringCompilation, WellKnownMember.System_Runtime_CompilerServices_RequiredMembersAttribute__ctor, diagnostics, Locations[0]); + _ = Binder.GetWellKnownTypeMember(DeclaringCompilation, WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor, diagnostics, Locations[0]); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index 1b560d0742d12..97ae4df10003a 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 diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index f654a111736ce..938d9c6dc393c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs @@ -1593,38 +1593,12 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r this.DeclaringCompilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor)); } - var requiredMembers = ArrayBuilder.GetInstance(); - foreach (var member in GetMembers()) + if (HasDeclaredRequiredMembers) { - switch (member) - { - case SourceFieldSymbol { IsRequired: true }: - case SourcePropertySymbol { IsRequired: true, IsOverride: false }: - case SourcePropertySymbol { IsRequired: true, IsOverride: true, OverriddenProperty.IsRequired: false }: - requiredMembers.Add(member); - break; - } - } - - if (requiredMembers.Any()) - { - var stringType = compilation.GetSpecialType(SpecialType.System_String); - // Because GetMembers() is already sorted in lexical order, we don't need to do - // any additional sorting here. - var nameConstants = requiredMembers.SelectAsArray( - static (member, stringType) => new TypedConstant(stringType, TypedConstantKind.Primitive, member.Name), - stringType); - var stringArrayType = ArrayTypeSymbol.CreateSZArray(stringType.ContainingAssembly, TypeWithAnnotations.Create(stringType)); - AddSynthesizedAttribute( ref attributes, - compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_RequiredMembersAttribute__ctor, - ImmutableArray.Create(new TypedConstant(stringArrayType, nameConstants)))); - - // PROTOTYPE(req): Add obsolete marker to constructors if required members and Obsolete hasn't already been emitted + compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_RequiredMemberAttribute__ctor)); } - - requiredMembers.Free(); } #endregion diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs index 26379673a21e5..0d8dba89b0121 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs @@ -1157,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 => @@ -1270,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..2bcd487cae60e 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); } + public 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 6c07312f1a32f..55b2b96c03cb9 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs @@ -1423,7 +1423,7 @@ internal bool ReportExplicitUseOfReservedAttributes(in DecodeWellKnownAttributeA diagnostics.Add(ErrorCode.ERR_ExplicitExtension, arguments.AttributeSyntaxOpt.Location); } else if ((reserved & ReservedAttributes.RequiredMemberAttribute) != 0 && - attribute.IsTargetAttribute(this, AttributeDescription.RequiredMembersAttribute)) + attribute.IsTargetAttribute(this, AttributeDescription.RequiredMemberAttribute)) { // Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. diagnostics.Add(ErrorCode.ERR_ExplicitRequiredMembers, arguments.AttributeSyntaxOpt.Location); diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs index e55fc29a04353..5853d2c6ef206 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; + public 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..aca8b08e8eb10 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); + public override bool HasDeclaredRequiredMembers => false; + public override Accessibility DeclaredAccessibility => Accessibility.Internal; public override TypeKind TypeKind => TypeKind.Class; diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index 6876bb77c5da6..7616fad39146a 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -610,7 +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_RequiredMembersAttribute: + case WellKnownType.System_Runtime_CompilerServices_RequiredMemberAttribute: // Not yet in the platform. continue; case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation: diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs index bdb7812c8f2d7..1594cc4c9d8c5 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 } } + public 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 index f3687d968b369..4a282d05e2072 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -13,24 +13,21 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols; [CompilerTrait(CompilerFeature.RequiredMembers)] public class RequiredMembersTests : CSharpTestBase { - private const string RequiredMembersAttribute = @" + private const string RequiredMemberAttribute = @" namespace System.Runtime.CompilerServices { - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] - public class RequiredMembersAttribute : Attribute + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, Inherited = false, AllowMultiple = false)] + public class RequiredMemberAttribute : Attribute { - public RequiredMembersAttribute(params string[] members) + public RequiredMemberAttribute() { - this.Members = members; } - - public string[] Members { get; } } } "; private CSharpCompilation CreateCompilationWithRequiredMembers(CSharpTestSource source, CSharpParseOptions? parseOptions = null, CSharpCompilationOptions? options = null) - => CreateCompilation(new[] { source, RequiredMembersAttribute }, options: options, parseOptions: parseOptions); + => CreateCompilation(new[] { source, RequiredMemberAttribute }, options: options, parseOptions: parseOptions); private Action ValidateRequiredMembersInModule(string[] memberPaths) { @@ -317,7 +314,7 @@ class required {} } [Fact] - public void MissingRequiredMembersAttribute() + public void MissingRequiredMemberAttribute() { var comp = CreateCompilation(@" class C @@ -325,15 +322,15 @@ class C public required int I { get; } }"); - // (2,7): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.RequiredMembersAttribute..ctor' + // (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.RequiredMembersAttribute", ".ctor").WithLocation(2, 7); + 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 MissingRequiredMembersAttributeCtor() + public void MissingRequiredMemberAttributeCtor() { var comp = CreateCompilation(@" class C @@ -344,21 +341,22 @@ class C namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] - public class RequiredMembersAttribute : Attribute + public class RequiredMemberAttribute : Attribute { + public RequiredMemberAttribute(int i) {} } } "); - // (2,7): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.RequiredMembersAttribute..ctor' + // (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.RequiredMembersAttribute", ".ctor").WithLocation(2, 7); + 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 RequiredMembersAttributeEmitted() + public void RequiredMemberAttributeEmitted() { var comp = CreateCompilationWithRequiredMembers(@" class C @@ -381,9 +379,8 @@ class C .class private auto ansi beforefieldinit C extends [netstandard]System.Object { - .custom instance void System.Runtime.CompilerServices.RequiredMembersAttribute::.ctor(string[]) = ( - 01 00 02 00 00 00 04 50 72 6f 70 05 46 69 65 6c - 64 00 00 + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 ) // Fields .field private int32 'k__BackingField' @@ -391,6 +388,9 @@ .field private int32 'k__BackingField' 01 00 00 00 ) .field public int32 Field + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 + ) // Methods .method public hidebysig specialname instance int32 get_Prop () cil managed @@ -434,6 +434,9 @@ .maxstack 8 // Properties .property instance int32 Prop() { + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 + ) .get instance int32 C::get_Prop() .set instance void C::set_Prop(int32) } @@ -442,7 +445,7 @@ .property instance int32 Prop() } [Fact] - public void RequiredMembersAttributeEmitted_OverrideRequiredProperty_MissingRequiredOnOverride() + public void RequiredMemberAttributeEmitted_OverrideRequiredProperty_MissingRequiredOnOverride() { var comp = CreateCompilationWithRequiredMembers(@" class Base @@ -463,7 +466,7 @@ class Dervied : Base } [Fact] - public void RequiredMembersAttributeEmitted_OverrideRequiredProperty() + public void RequiredMemberAttributeEmitted_OverrideRequiredProperty() { var comp = CreateCompilationWithRequiredMembers(@" class Base @@ -485,8 +488,8 @@ class Derived : Base .class private auto ansi beforefieldinit Base extends [netstandard]System.Object { - .custom instance void System.Runtime.CompilerServices.RequiredMembersAttribute::.ctor(string[]) = ( - 01 00 01 00 00 00 04 50 72 6f 70 00 00 + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 ) // Fields .field private int32 'k__BackingField' @@ -536,6 +539,9 @@ .maxstack 8 // Properties .property instance int32 Prop() { + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 + ) .get instance int32 Base::get_Prop() .set instance void Base::set_Prop(int32) } @@ -546,6 +552,9 @@ .property instance int32 Prop() .class private auto ansi beforefieldinit Derived extends Base { + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 + ) // Fields .field private int32 'k__BackingField' .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( @@ -594,6 +603,9 @@ .maxstack 8 // Properties .property instance int32 Prop() { + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 + ) .get instance int32 Derived::get_Prop() .set instance void Derived::set_Prop(int32) } @@ -602,7 +614,7 @@ .property instance int32 Prop() } [Fact] - public void RequiredMembersAttributeEmitted_AddRequiredOnOverride() + public void RequiredMemberAttributeEmitted_AddRequiredOnOverride() { var comp = CreateCompilationWithRequiredMembers(@" class Base @@ -686,8 +698,8 @@ .property instance int32 Prop() .class private auto ansi beforefieldinit Derived extends Base { - .custom instance void System.Runtime.CompilerServices.RequiredMembersAttribute::.ctor(string[]) = ( - 01 00 01 00 00 00 04 50 72 6f 70 00 00 + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 ) // Fields .field private int32 'k__BackingField' @@ -737,6 +749,9 @@ .maxstack 8 // Properties .property instance int32 Prop() { + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 + ) .get instance int32 Derived::get_Prop() .set instance void Derived::set_Prop(int32) } @@ -747,6 +762,9 @@ .property instance int32 Prop() .class private auto ansi beforefieldinit DerivedDerived extends Derived { + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 + ) // Fields .field private int32 'k__BackingField' .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( @@ -795,6 +813,9 @@ .maxstack 8 // Properties .property instance int32 Prop() { + .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( + 01 00 00 00 + ) .get instance int32 DerivedDerived::get_Prop() .set instance void DerivedDerived::set_Prop(int32) } @@ -1057,21 +1078,33 @@ class C : I } [Fact] - public void UsingRequiredMembersAttributeExplicitly() + public void UsingRequiredMemberAttributeExplicitly() { var comp = CreateCompilationWithRequiredMembers(@" using System.Runtime.CompilerServices; -[RequiredMembers(new[] { ""Prop"" })] +[RequiredMember] class C { + [RequiredMember] public int Prop { get; set; } + [RequiredMember] + public int Field; } "); comp.VerifyDiagnostics( // (3,2): error CS9504: Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - // [RequiredMembers(new[] { "Prop" })] - Diagnostic(ErrorCode.ERR_ExplicitRequiredMembers, @"RequiredMembers(new[] { ""Prop"" })").WithLocation(3, 2) + // [RequiredMember] + Diagnostic(ErrorCode.ERR_ExplicitRequiredMembers, "RequiredMember").WithLocation(3, 2), + // (6,6): error CS9504: Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + // [RequiredMember] + Diagnostic(ErrorCode.ERR_ExplicitRequiredMembers, "RequiredMember").WithLocation(6, 6), + // (8,6): error CS9504: Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + // [RequiredMember] + Diagnostic(ErrorCode.ERR_ExplicitRequiredMembers, "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"); diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index 292669e9d8219..18f920c509876 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -479,6 +479,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 RequiredMembersAttribute = new AttributeDescription("System.Runtime.CompilerServices", "RequiredMembersAttribute", s_signatures_HasThis_Void_SzArray_String_Only); + 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 b17789a712872..b43227dd5bd20 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -517,8 +517,7 @@ internal enum WellKnownMember System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear, - System_Runtime_CompilerServices_RequiredMembersAttribute__ctor, - System_Runtime_CompilerServices_RequiredMembersAttribute__get_Members, + System_Runtime_CompilerServices_RequiredMemberAttribute__ctor, Count diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index b2f9570027bf1..6b885f3b9c586 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3537,18 +3537,10 @@ static WellKnownMembers() // System_Runtime_CompilerServices_RequiredMembersAttribute__ctor (byte)MemberFlags.Constructor, // Flags - (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_RequiredMembersAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId - 0, // Arity - 1, // Method Signature - (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type - (byte)SignatureTypeCode.SZArray, (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_String, - - // System_Runtime_CompilerServices_RequiredMembersAttribute__get_Members - (byte)(MemberFlags.PropertyGet | MemberFlags.Static), // Flags - (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_RequiredMembersAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId + (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_RequiredMemberAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId 0, // Arity 0, // Method Signature - (byte)SignatureTypeCode.SZArray, (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Collections_Generic_EqualityComparer_T,// Return Type + (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type }; @@ -3994,8 +3986,7 @@ static WellKnownMembers() "Append", // System_Text_StringBuilder__AppendObject ".ctor", // System_Text_StringBuilder__ctor "ToStringAndClear", // System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear - ".ctor", // System_Runtime_CompilerServices_RequiredMembersAttribute__ctor - "get_Members", // System_Runtime_CompilerServices_RequiredMembersAttribute__get_Members + ".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 5962d69453a08..fd3366365333f 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -317,7 +317,7 @@ internal enum WellKnownType System_ArgumentNullException, - System_Runtime_CompilerServices_RequiredMembersAttribute, + System_Runtime_CompilerServices_RequiredMemberAttribute, NextAvailable, // Remember to update the AllWellKnownTypes tests when making changes here @@ -628,7 +628,7 @@ internal static class WellKnownTypes "System.Runtime.CompilerServices.DefaultInterpolatedStringHandler", "System.ArgumentNullException", - "System.Runtime.CompilerServices.RequiredMembersAttribute" + "System.Runtime.CompilerServices.RequiredMemberAttribute" }; private static readonly Dictionary s_nameToTypeIdMap = new Dictionary((int)Count); From 5f818c1f08934df1d1e047cc0051667cf561a0d1 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Wed, 26 Jan 2022 15:37:59 -0800 Subject: [PATCH 04/11] Fix EE --- .../Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs | 2 +- .../Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs index a175df54f20b1..4619b76bdf234 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/DisplayClassVariable.cs @@ -159,7 +159,7 @@ public override bool IsVolatile get { return false; } } - public override bool IsRequired => throw ExceptionUtilities.Unreachable; + internal override bool IsRequired => throw ExceptionUtilities.Unreachable; public override FlowAnalysisAnnotations FlowAnalysisAnnotations { diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs index 69fa80e320486..aa957afb96579 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; } } + public override bool HasDeclaredRequiredMembers => throw ExceptionUtilities.Unreachable; + public override ImmutableArray GetMembers() { return _methods.Cast(); From 7ac65bc56222b6a13f1f43ac3cab0261e298aa0b Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Wed, 26 Jan 2022 16:20:30 -0800 Subject: [PATCH 05/11] Adjust test names for clarity, update wellknown tests. --- .../Symbol/Symbols/MissingSpecialMember.cs | 1 + .../Symbol/Symbols/RequiredMembersTests.cs | 336 +++++++++--------- .../WellKnownTypeValidationTests.vb | 7 +- 3 files changed, 174 insertions(+), 170 deletions(-) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index 7616fad39146a..1b7aff577023d 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -965,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/RequiredMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs index 4a282d05e2072..7e5ecd4981724 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -867,192 +867,192 @@ public void RequiredMembersMustBeAsVisibleAsContainingType() var comp = CreateCompilationWithRequiredMembers(@" #pragma warning disable CS0649 // Never assigned #pragma warning disable CS0169 // Never used -public class C1 +public class PublicClass { - public required int Prop1 { get; set; } - internal protected required int Prop2 { get; set; } - internal required int Prop3 { get; set; } - protected required int Prop4 { get; set; } - private protected required int Prop5 { get; set; } - private required int Prop6 { get; set; } - public required int Field1; - internal protected required int Field2; - internal required int Field3; - protected required int Field4; - private protected required int Field5; - private required int Field6; + 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; } -internal class C2 +internal class InternalClass { - public required int Prop1 { get; set; } - internal protected required int Prop2 { get; set; } - internal required int Prop3 { get; set; } - protected required int Prop4 { get; set; } - private protected required int Prop5 { get; set; } - private required int Prop6 { get; set; } - public required int Field1; - internal protected required int Field2; - internal required int Field3; - protected required int Field4; - private protected required int Field5; - private required int Field6; + 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; } internal class Outer { - protected internal class C3 + protected internal class ProtectedInternalClass { - public required int Prop1 { get; set; } - internal required int Prop2 { get; set; } - internal protected required int Prop3 { get; set; } - protected required int Prop4 { get; set; } - private protected required int Prop5 { get; set; } - private required int Prop6 { get; set; } - public required int Field1; - internal required int Field2; - internal protected required int Field3; - protected required int Field4; - private protected required int Field5; - private required int Field6; + 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; } - protected class C4 + protected class ProtectedClass { - public required int Prop1 { get; set; } - internal protected required int Prop2 { get; set; } - internal required int Prop3 { get; set; } - protected required int Prop4 { get; set; } - private protected required int Prop5 { get; set; } - private required int Prop6 { get; set; } - public required int Field1; - internal protected required int Field2; - internal required int Field3; - protected required int Field4; - private protected required int Field5; - private required int Field6; + 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; } - private protected class C5 + private protected class PrivateProtectedClass { - public required int Prop1 { get; set; } - internal protected required int Prop2 { get; set; } - internal required int Prop3 { get; set; } - protected required int Prop4 { get; set; } - private protected required int Prop5 { get; set; } - private required int Prop6 { get; set; } - public required int Field1; - internal protected required int Field2; - internal required int Field3; - protected required int Field4; - private protected required int Field5; - private required int Field6; + 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; } - private class C6 + private class PrivateClass { - public required int Prop1 { get; set; } - internal protected required int Prop2 { get; set; } - internal required int Prop3 { get; set; } - protected required int Prop4 { get; set; } - private protected required int Prop5 { get; set; } - private required int Prop6 { get; set; } - public required int Field1; - internal protected required int Field2; - internal required int Field3; - protected required int Field4; - private protected required int Field5; - private required int Field6; + 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 'C1.Prop2' cannot be less visible than the containing type 'C1'. - // internal protected required int Prop2 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop2").WithArguments("C1.Prop2", "C1").WithLocation(7, 37), - // (8,27): error CS9503: Required member 'C1.Prop3' cannot be less visible than the containing type 'C1'. - // internal required int Prop3 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop3").WithArguments("C1.Prop3", "C1").WithLocation(8, 27), - // (9,28): error CS9503: Required member 'C1.Prop4' cannot be less visible than the containing type 'C1'. - // protected required int Prop4 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop4").WithArguments("C1.Prop4", "C1").WithLocation(9, 28), - // (10,36): error CS9503: Required member 'C1.Prop5' cannot be less visible than the containing type 'C1'. - // private protected required int Prop5 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop5").WithArguments("C1.Prop5", "C1").WithLocation(10, 36), - // (11,26): error CS9503: Required member 'C1.Prop6' cannot be less visible than the containing type 'C1'. - // private required int Prop6 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("C1.Prop6", "C1").WithLocation(11, 26), - // (13,37): error CS9503: Required member 'C1.Field2' cannot be less visible than the containing type 'C1'. - // internal protected required int Field2; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field2").WithArguments("C1.Field2", "C1").WithLocation(13, 37), - // (14,27): error CS9503: Required member 'C1.Field3' cannot be less visible than the containing type 'C1'. - // internal required int Field3; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field3").WithArguments("C1.Field3", "C1").WithLocation(14, 27), - // (15,28): error CS9503: Required member 'C1.Field4' cannot be less visible than the containing type 'C1'. - // protected required int Field4; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field4").WithArguments("C1.Field4", "C1").WithLocation(15, 28), - // (16,36): error CS9503: Required member 'C1.Field5' cannot be less visible than the containing type 'C1'. - // private protected required int Field5; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field5").WithArguments("C1.Field5", "C1").WithLocation(16, 36), - // (17,26): error CS9503: Required member 'C1.Field6' cannot be less visible than the containing type 'C1'. - // private required int Field6; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("C1.Field6", "C1").WithLocation(17, 26), - // (24,28): error CS9503: Required member 'C2.Prop4' cannot be less visible than the containing type 'C2'. - // protected required int Prop4 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop4").WithArguments("C2.Prop4", "C2").WithLocation(24, 28), - // (25,36): error CS9503: Required member 'C2.Prop5' cannot be less visible than the containing type 'C2'. - // private protected required int Prop5 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop5").WithArguments("C2.Prop5", "C2").WithLocation(25, 36), - // (26,26): error CS9503: Required member 'C2.Prop6' cannot be less visible than the containing type 'C2'. - // private required int Prop6 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("C2.Prop6", "C2").WithLocation(26, 26), - // (30,28): error CS9503: Required member 'C2.Field4' cannot be less visible than the containing type 'C2'. - // protected required int Field4; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field4").WithArguments("C2.Field4", "C2").WithLocation(30, 28), - // (31,36): error CS9503: Required member 'C2.Field5' cannot be less visible than the containing type 'C2'. - // private protected required int Field5; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field5").WithArguments("C2.Field5", "C2").WithLocation(31, 36), - // (32,26): error CS9503: Required member 'C2.Field6' cannot be less visible than the containing type 'C2'. - // private required int Field6; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("C2.Field6", "C2").WithLocation(32, 26), - // (39,31): error CS9503: Required member 'Outer.C3.Prop2' cannot be less visible than the containing type 'Outer.C3'. - // internal required int Prop2 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop2").WithArguments("Outer.C3.Prop2", "Outer.C3").WithLocation(39, 31), - // (41,32): error CS9503: Required member 'Outer.C3.Prop4' cannot be less visible than the containing type 'Outer.C3'. - // protected required int Prop4 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop4").WithArguments("Outer.C3.Prop4", "Outer.C3").WithLocation(41, 32), - // (42,40): error CS9503: Required member 'Outer.C3.Prop5' cannot be less visible than the containing type 'Outer.C3'. - // private protected required int Prop5 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop5").WithArguments("Outer.C3.Prop5", "Outer.C3").WithLocation(42, 40), - // (43,30): error CS9503: Required member 'Outer.C3.Prop6' cannot be less visible than the containing type 'Outer.C3'. - // private required int Prop6 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("Outer.C3.Prop6", "Outer.C3").WithLocation(43, 30), - // (45,31): error CS9503: Required member 'Outer.C3.Field2' cannot be less visible than the containing type 'Outer.C3'. - // internal required int Field2; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field2").WithArguments("Outer.C3.Field2", "Outer.C3").WithLocation(45, 31), - // (47,32): error CS9503: Required member 'Outer.C3.Field4' cannot be less visible than the containing type 'Outer.C3'. - // protected required int Field4; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field4").WithArguments("Outer.C3.Field4", "Outer.C3").WithLocation(47, 32), - // (48,40): error CS9503: Required member 'Outer.C3.Field5' cannot be less visible than the containing type 'Outer.C3'. - // private protected required int Field5; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field5").WithArguments("Outer.C3.Field5", "Outer.C3").WithLocation(48, 40), - // (49,30): error CS9503: Required member 'Outer.C3.Field6' cannot be less visible than the containing type 'Outer.C3'. - // private required int Field6; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("Outer.C3.Field6", "Outer.C3").WithLocation(49, 30), - // (57,40): error CS9503: Required member 'Outer.C4.Prop5' cannot be less visible than the containing type 'Outer.C4'. - // private protected required int Prop5 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop5").WithArguments("Outer.C4.Prop5", "Outer.C4").WithLocation(57, 40), - // (58,30): error CS9503: Required member 'Outer.C4.Prop6' cannot be less visible than the containing type 'Outer.C4'. - // private required int Prop6 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("Outer.C4.Prop6", "Outer.C4").WithLocation(58, 30), - // (63,40): error CS9503: Required member 'Outer.C4.Field5' cannot be less visible than the containing type 'Outer.C4'. - // private protected required int Field5; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field5").WithArguments("Outer.C4.Field5", "Outer.C4").WithLocation(63, 40), - // (64,30): error CS9503: Required member 'Outer.C4.Field6' cannot be less visible than the containing type 'Outer.C4'. - // private required int Field6; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("Outer.C4.Field6", "Outer.C4").WithLocation(64, 30), - // (73,30): error CS9503: Required member 'Outer.C5.Prop6' cannot be less visible than the containing type 'Outer.C5'. - // private required int Prop6 { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Prop6").WithArguments("Outer.C5.Prop6", "Outer.C5").WithLocation(73, 30), - // (79,30): error CS9503: Required member 'Outer.C5.Field6' cannot be less visible than the containing type 'Outer.C5'. - // private required int Field6; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "Field6").WithArguments("Outer.C5.Field6", "Outer.C5").WithLocation(79, 30) + // (7,37): error CS9503: Required member 'PublicClass.InternalProtectedProperty' cannot be less visible than the containing type 'PublicClass'. + // internal protected required int InternalProtectedProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalProtectedProperty").WithArguments("PublicClass.InternalProtectedProperty", "PublicClass").WithLocation(7, 37), + // (8,27): error CS9503: Required member 'PublicClass.InternalProperty' cannot be less visible than the containing type 'PublicClass'. + // internal required int InternalProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalProperty").WithArguments("PublicClass.InternalProperty", "PublicClass").WithLocation(8, 27), + // (9,28): error CS9503: Required member 'PublicClass.ProtectedProperty' cannot be less visible than the containing type 'PublicClass'. + // protected required int ProtectedProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedProperty").WithArguments("PublicClass.ProtectedProperty", "PublicClass").WithLocation(9, 28), + // (10,36): error CS9503: Required member 'PublicClass.PrivateProtectedProperty' cannot be less visible than the containing type 'PublicClass'. + // private protected required int PrivateProtectedProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("PublicClass.PrivateProtectedProperty", "PublicClass").WithLocation(10, 36), + // (11,26): error CS9503: Required member 'PublicClass.PrivateProperty' cannot be less visible than the containing type 'PublicClass'. + // private required int PrivateProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("PublicClass.PrivateProperty", "PublicClass").WithLocation(11, 26), + // (13,37): error CS9503: Required member 'PublicClass.InternalProtectedField' cannot be less visible than the containing type 'PublicClass'. + // internal protected required int InternalProtectedField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalProtectedField").WithArguments("PublicClass.InternalProtectedField", "PublicClass").WithLocation(13, 37), + // (14,27): error CS9503: Required member 'PublicClass.InternalField' cannot be less visible than the containing type 'PublicClass'. + // internal required int InternalField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalField").WithArguments("PublicClass.InternalField", "PublicClass").WithLocation(14, 27), + // (15,28): error CS9503: Required member 'PublicClass.ProtectedField' cannot be less visible than the containing type 'PublicClass'. + // protected required int ProtectedField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedField").WithArguments("PublicClass.ProtectedField", "PublicClass").WithLocation(15, 28), + // (16,36): error CS9503: Required member 'PublicClass.PrivateProtectedField' cannot be less visible than the containing type 'PublicClass'. + // private protected required int PrivateProtectedField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("PublicClass.PrivateProtectedField", "PublicClass").WithLocation(16, 36), + // (17,26): error CS9503: Required member 'PublicClass.PrivateField' cannot be less visible than the containing type 'PublicClass'. + // private required int PrivateField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("PublicClass.PrivateField", "PublicClass").WithLocation(17, 26), + // (24,28): error CS9503: Required member 'InternalClass.ProtectedProperty' cannot be less visible than the containing type 'InternalClass'. + // protected required int ProtectedProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedProperty").WithArguments("InternalClass.ProtectedProperty", "InternalClass").WithLocation(24, 28), + // (25,36): error CS9503: Required member 'InternalClass.PrivateProtectedProperty' cannot be less visible than the containing type 'InternalClass'. + // private protected required int PrivateProtectedProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("InternalClass.PrivateProtectedProperty", "InternalClass").WithLocation(25, 36), + // (26,26): error CS9503: Required member 'InternalClass.PrivateProperty' cannot be less visible than the containing type 'InternalClass'. + // private required int PrivateProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("InternalClass.PrivateProperty", "InternalClass").WithLocation(26, 26), + // (30,28): error CS9503: Required member 'InternalClass.ProtectedField' cannot be less visible than the containing type 'InternalClass'. + // protected required int ProtectedField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedField").WithArguments("InternalClass.ProtectedField", "InternalClass").WithLocation(30, 28), + // (31,36): error CS9503: Required member 'InternalClass.PrivateProtectedField' cannot be less visible than the containing type 'InternalClass'. + // private protected required int PrivateProtectedField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("InternalClass.PrivateProtectedField", "InternalClass").WithLocation(31, 36), + // (32,26): error CS9503: Required member 'InternalClass.PrivateField' cannot be less visible than the containing type 'InternalClass'. + // private required int PrivateField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("InternalClass.PrivateField", "InternalClass").WithLocation(32, 26), + // (40,31): error CS9503: Required member 'Outer.ProtectedInternalClass.InternalProperty' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. + // internal required int InternalProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalProperty").WithArguments("Outer.ProtectedInternalClass.InternalProperty", "Outer.ProtectedInternalClass").WithLocation(40, 31), + // (41,32): error CS9503: Required member 'Outer.ProtectedInternalClass.ProtectedProperty' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. + // protected required int ProtectedProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedProperty").WithArguments("Outer.ProtectedInternalClass.ProtectedProperty", "Outer.ProtectedInternalClass").WithLocation(41, 32), + // (42,40): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateProtectedProperty' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. + // private protected required int PrivateProtectedProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("Outer.ProtectedInternalClass.PrivateProtectedProperty", "Outer.ProtectedInternalClass").WithLocation(42, 40), + // (43,30): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateProperty' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. + // private required int PrivateProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("Outer.ProtectedInternalClass.PrivateProperty", "Outer.ProtectedInternalClass").WithLocation(43, 30), + // (46,31): error CS9503: Required member 'Outer.ProtectedInternalClass.InternalField' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. + // internal required int InternalField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalField").WithArguments("Outer.ProtectedInternalClass.InternalField", "Outer.ProtectedInternalClass").WithLocation(46, 31), + // (47,32): error CS9503: Required member 'Outer.ProtectedInternalClass.ProtectedField' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. + // protected required int ProtectedField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedField").WithArguments("Outer.ProtectedInternalClass.ProtectedField", "Outer.ProtectedInternalClass").WithLocation(47, 32), + // (48,40): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateProtectedField' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. + // private protected required int PrivateProtectedField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("Outer.ProtectedInternalClass.PrivateProtectedField", "Outer.ProtectedInternalClass").WithLocation(48, 40), + // (49,30): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateField' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. + // private required int PrivateField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("Outer.ProtectedInternalClass.PrivateField", "Outer.ProtectedInternalClass").WithLocation(49, 30), + // (57,40): error CS9503: Required member 'Outer.ProtectedClass.PrivateProtectedProperty' cannot be less visible than the containing type 'Outer.ProtectedClass'. + // private protected required int PrivateProtectedProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("Outer.ProtectedClass.PrivateProtectedProperty", "Outer.ProtectedClass").WithLocation(57, 40), + // (58,30): error CS9503: Required member 'Outer.ProtectedClass.PrivateProperty' cannot be less visible than the containing type 'Outer.ProtectedClass'. + // private required int PrivateProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("Outer.ProtectedClass.PrivateProperty", "Outer.ProtectedClass").WithLocation(58, 30), + // (63,40): error CS9503: Required member 'Outer.ProtectedClass.PrivateProtectedField' cannot be less visible than the containing type 'Outer.ProtectedClass'. + // private protected required int PrivateProtectedField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("Outer.ProtectedClass.PrivateProtectedField", "Outer.ProtectedClass").WithLocation(63, 40), + // (64,30): error CS9503: Required member 'Outer.ProtectedClass.PrivateField' cannot be less visible than the containing type 'Outer.ProtectedClass'. + // private required int PrivateField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("Outer.ProtectedClass.PrivateField", "Outer.ProtectedClass").WithLocation(64, 30), + // (73,30): error CS9503: Required member 'Outer.PrivateProtectedClass.PrivateProperty' cannot be less visible than the containing type 'Outer.PrivateProtectedClass'. + // private required int PrivateProperty { get; set; } + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("Outer.PrivateProtectedClass.PrivateProperty", "Outer.PrivateProtectedClass").WithLocation(73, 30), + // (79,30): error CS9503: Required member 'Outer.PrivateProtectedClass.PrivateField' cannot be less visible than the containing type 'Outer.PrivateProtectedClass'. + // private required int PrivateField; + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("Outer.PrivateProtectedClass.PrivateField", "Outer.PrivateProtectedClass").WithLocation(79, 30) ); } diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index a8b6b5df00e13..1ef84bdef34dd 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 @@ -696,7 +698,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, From 6f011627cd3a11a1de05a5b3803f4b12fa1eb2b0 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Wed, 26 Jan 2022 16:25:55 -0800 Subject: [PATCH 06/11] Final revisions --- .../Core/Portable/Symbols/Attributes/AttributeDescription.cs | 1 - src/Compilers/Test/Core/CompilationVerifier.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index 18f920c509876..0cc374d095026 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -199,7 +199,6 @@ static AttributeDescription() private static readonly byte[][] s_signatures_HasThis_Void_Only = { s_signature_HasThis_Void }; private static readonly byte[][] s_signatures_HasThis_Void_String_Only = { s_signature_HasThis_Void_String }; - private static readonly byte[][] s_signatures_HasThis_Void_SzArray_String_Only = { s_signature_HasThis_Void_SzArray_String }; private static readonly byte[][] s_signatures_HasThis_Void_Type_Only = { s_signature_HasThis_Void_Type }; private static readonly byte[][] s_signatures_HasThis_Void_Boolean_Only = { s_signature_HasThis_Void_Boolean }; diff --git a/src/Compilers/Test/Core/CompilationVerifier.cs b/src/Compilers/Test/Core/CompilationVerifier.cs index a23902e55a141..1ed62d8b828c8 100644 --- a/src/Compilers/Test/Core/CompilationVerifier.cs +++ b/src/Compilers/Test/Core/CompilationVerifier.cs @@ -193,7 +193,7 @@ public void VerifyTypeIL(string typeName, string expected) Assert.True(found, "Could not find type named " + typeName); } } - AssertEx.AssertEqualToleratingWhitespaceDifferences(expected, output.ToString().Replace("\t", " "), escapeQuotes: false); + AssertEx.AssertEqualToleratingWhitespaceDifferences(expected, output.ToString(), escapeQuotes: false); } public void Emit(string expectedOutput, int? expectedReturnCode, string[] args, IEnumerable manifestResources, EmitOptions emitOptions, Verification peVerify, SignatureDescription[] expectedSignatures) From 84c57163ef27be801d0c69ad716b17ecc95b929b Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 28 Jan 2022 14:21:03 -0800 Subject: [PATCH 07/11] PR feedback. --- .../CSharp/Portable/CSharpResources.resx | 4 +- .../Declarations/DeclarationTreeBuilder.cs | 23 +++ .../Declarations/SingleTypeDeclaration.cs | 4 + ...ymousManager.TypeOrDelegatePublicSymbol.cs | 2 +- .../AnonymousType.TemplateSymbol.cs | 2 +- .../Portable/Symbols/ErrorTypeSymbol.cs | 2 +- .../Symbols/Metadata/PE/PENamedTypeSymbol.cs | 2 +- .../Portable/Symbols/NamedTypeSymbol.cs | 2 +- .../Symbols/NativeIntegerTypeSymbol.cs | 2 +- .../Retargeting/RetargetingNamedTypeSymbol.cs | 2 +- .../Source/SourceMemberContainerSymbol.cs | 4 +- ...berContainerSymbol_ImplementationChecks.cs | 3 +- .../Symbols/SubstitutedNamedTypeSymbol.cs | 2 +- .../CSharp/Portable/Symbols/Symbol.cs | 2 +- .../Portable/Symbols/SymbolExtensions.cs | 7 +- .../Synthesized/SynthesizedContainer.cs | 2 +- .../SynthesizedEmbeddedAttributeSymbol.cs | 2 +- .../Portable/xlf/CSharpResources.cs.xlf | 10 +- .../Portable/xlf/CSharpResources.de.xlf | 10 +- .../Portable/xlf/CSharpResources.es.xlf | 10 +- .../Portable/xlf/CSharpResources.fr.xlf | 10 +- .../Portable/xlf/CSharpResources.it.xlf | 10 +- .../Portable/xlf/CSharpResources.ja.xlf | 10 +- .../Portable/xlf/CSharpResources.ko.xlf | 10 +- .../Portable/xlf/CSharpResources.pl.xlf | 10 +- .../Portable/xlf/CSharpResources.pt-BR.xlf | 10 +- .../Portable/xlf/CSharpResources.ru.xlf | 10 +- .../Portable/xlf/CSharpResources.tr.xlf | 10 +- .../Portable/xlf/CSharpResources.zh-Hans.xlf | 10 +- .../Portable/xlf/CSharpResources.zh-Hant.xlf | 10 +- .../Symbol/Symbols/MockNamedTypeSymbol.cs | 2 +- .../Symbol/Symbols/RequiredMembersTests.cs | 133 +++++++++++++----- .../Symbols/EENamedTypeSymbol.cs | 2 +- 33 files changed, 207 insertions(+), 127 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index efe21cbb9028b..da6bc6e576a5f 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6942,7 +6942,7 @@ 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 not be named 'required'. + Types and aliases cannot be named 'required'. required members @@ -6957,6 +6957,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Required member '{0}' cannot be less visible than the containing type '{1}'. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. 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/Symbols/AnonymousTypes/PublicSymbols/AnonymousManager.TypeOrDelegatePublicSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/PublicSymbols/AnonymousManager.TypeOrDelegatePublicSymbol.cs index acb5904811b69..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,7 +123,7 @@ internal sealed override bool HasSpecialName get { return false; } } - public override bool HasDeclaredRequiredMembers => false; + internal override bool HasDeclaredRequiredMembers => false; public sealed override ImmutableArray GetTypeMembers() { 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 602b689bcb719..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,7 +189,7 @@ internal void AdjustLocation(Location location) } } - public override bool HasDeclaredRequiredMembers => false; + internal override bool HasDeclaredRequiredMembers => false; public override ImmutableArray GetMembers() { diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs index 665f92169e6a7..286394b84209e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.cs @@ -130,7 +130,7 @@ public override IEnumerable MemberNames } } - public override sealed bool HasDeclaredRequiredMembers => false; + internal sealed override bool HasDeclaredRequiredMembers => false; /// /// Get all the members of this symbol. diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index 15e273c4591fe..dc8229e580697 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs @@ -825,7 +825,7 @@ private static ICollection CreateReadOnlyMemberNames(HashSet nam } // PROTOTYPE(req): Implement - public override bool HasDeclaredRequiredMembers => false; + internal override bool HasDeclaredRequiredMembers => false; public override ImmutableArray GetMembers() { diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index 6338542a2841e..7cb9d7c0f7086 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs @@ -497,7 +497,7 @@ internal abstract bool MangleName /// /// True if this type declares any required members. It does not recursively check up the tree for _all_ required members. /// - public abstract bool HasDeclaredRequiredMembers { get; } + 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 bd86f40c2b745..9487c7a2ab270 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs @@ -46,7 +46,7 @@ internal NativeIntegerTypeSymbol(NamedTypeSymbol underlyingType) : base(underlyi public override IEnumerable MemberNames => GetMembers().Select(m => m.Name); - public override bool HasDeclaredRequiredMembers => false; + internal override bool HasDeclaredRequiredMembers => false; /// /// Certain members from the underlying types are not exposed from the native integer types: diff --git a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs index a131488cb034f..13fb6fd8f15eb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingNamedTypeSymbol.cs @@ -120,7 +120,7 @@ public override IEnumerable MemberNames } } - public override bool HasDeclaredRequiredMembers => _underlyingType.HasDeclaredRequiredMembers; + internal override bool HasDeclaredRequiredMembers => _underlyingType.HasDeclaredRequiredMembers; public override ImmutableArray GetMembers() { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index 93fab0306e1da..94a6a797825de 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -1326,7 +1326,7 @@ private void CheckMemberNameDistinctFromType(Symbol member, BindingDiagnosticBag } } - public override bool HasDeclaredRequiredMembers + internal override bool HasDeclaredRequiredMembers { get { @@ -1335,7 +1335,7 @@ public override bool HasDeclaredRequiredMembers return hasDeclaredMembers; } - hasDeclaredMembers = GetMembersUnordered().Any(SymbolExtensions.IsRequired); + hasDeclaredMembers = declaration.Declarations.Any(static decl => decl.HasRequiredMembers); _flags.SetHasDeclaredRequiredMembers(hasDeclaredMembers); return hasDeclaredMembers; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs index 60b8c61a80f20..8c63818713e3c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs @@ -1420,7 +1420,8 @@ private static void CheckNonOverrideMember( diagnostics.Add(ErrorCode.WRN_NewOrOverrideExpected, hidingMemberLocation, hidingMember, hiddenMember); diagnosticAdded = true; } - else if (hiddenMember.IsRequired()) + + if (hiddenMember.IsRequired()) { // Required member '{0}' cannot be hidden by '{1}'. diagnostics.Add(ErrorCode.ERR_RequiredMembersCannotBeHidden, hidingMemberLocation, hiddenMember, hidingMember); diff --git a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs index 2bcd487cae60e..5f62fd41389e3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SubstitutedNamedTypeSymbol.cs @@ -204,7 +204,7 @@ public sealed override ImmutableArray GetTypeMembers(string nam return OriginalDefinition.GetTypeMembers(name, arity).SelectAsArray((t, self) => t.AsMember(self), this); } - public sealed override bool HasDeclaredRequiredMembers => OriginalDefinition.HasDeclaredRequiredMembers; + internal sealed override bool HasDeclaredRequiredMembers => OriginalDefinition.HasDeclaredRequiredMembers; public sealed override ImmutableArray GetMembers() { diff --git a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs index 55b2b96c03cb9..412fd1ddd385a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs @@ -1425,7 +1425,7 @@ internal bool ReportExplicitUseOfReservedAttributes(in DecodeWellKnownAttributeA else if ((reserved & ReservedAttributes.RequiredMemberAttribute) != 0 && attribute.IsTargetAttribute(this, AttributeDescription.RequiredMemberAttribute)) { - // Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + // Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. diagnostics.Add(ErrorCode.ERR_ExplicitRequiredMembers, arguments.AttributeSyntaxOpt.Location); } else diff --git a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs index e3229851e39d6..2fa9cce9e30d4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs @@ -840,11 +840,6 @@ internal static bool HasAsyncMethodBuilderAttribute(this Symbol symbol, [NotNull return false; } - internal static bool IsRequired(this Symbol symbol) - => symbol switch - { - FieldSymbol { IsRequired: true } or PropertySymbol { IsRequired: true } => true, - _ => 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/SynthesizedContainer.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs index 5853d2c6ef206..96dcf312f9f03 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedContainer.cs @@ -132,7 +132,7 @@ internal override ImmutableArray TypeArgumentsWithAnnotatio internal sealed override bool IsInterpolatedStringHandlerType => false; - public sealed override bool HasDeclaredRequiredMembers => false; + internal sealed override bool HasDeclaredRequiredMembers => false; public override ImmutableArray GetMembers() { diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs index aca8b08e8eb10..a03039d83a6ca 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs @@ -67,7 +67,7 @@ public SynthesizedEmbeddedAttributeSymbolBase( public override IEnumerable MemberNames => Constructors.Select(m => m.Name); - public override bool HasDeclaredRequiredMembers => false; + internal override bool HasDeclaredRequiredMembers => false; public override Accessibility DeclaredAccessibility => Accessibility.Internal; diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 3839b2d3e896c..8db0bdf94260b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 89783b8f2df85..6fe7da0daa187 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index d2f3f7759ce34..d294f3d1435b5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 3a1922409a624..b3f957b3c8b48 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 876d0de8aa0c2..5654089ac4547 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 361d1431522a2..d9f51e48ceb7c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 54db9f4a9cb80..d46ccc519d7b7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11428,4 +11428,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 1df1eab7f5e08..3d91824004e24 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 2f1f82ade1a33..2856c10d04cc2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 3575f8940b137..7704575a7fd23 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 688141c10c389..49213e877ee5f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 3d083e9066b9b..d06603cbadefc 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11434,4 +11434,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 0de23b5db9925..57dc766472c45 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -433,8 +433,8 @@ - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. - Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1108,8 +1108,8 @@ - Types and aliases cannot not be named 'required'. - Types and aliases cannot not be named 'required'. + Types and aliases cannot be named 'required'. + Types and aliases cannot be named 'required'. @@ -11429,4 +11429,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - \ No newline at end of file + diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs index 1594cc4c9d8c5..d5e358d3b6939 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs @@ -89,7 +89,7 @@ public override IEnumerable MemberNames } } - public override bool HasDeclaredRequiredMembers => throw new NotImplementedException(); + internal override bool HasDeclaredRequiredMembers => throw new NotImplementedException(); public override ImmutableArray GetMembers() { diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs index 7e5ecd4981724..5a8338ec75577 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols; @@ -26,7 +27,7 @@ public RequiredMemberAttribute() } "; - private CSharpCompilation CreateCompilationWithRequiredMembers(CSharpTestSource source, CSharpParseOptions? parseOptions = null, CSharpCompilationOptions? options = null) + private CSharpCompilation CreateCompilationWithRequiredMembers(CSharpTestSource source, CSharpParseOptions? parseOptions = null, CSharpCompilationOptions? options = null, TargetFramework tfm = TargetFramework.NetCoreApp) => CreateCompilation(new[] { source, RequiredMemberAttribute }, options: options, parseOptions: parseOptions); private Action ValidateRequiredMembersInModule(string[] memberPaths) @@ -285,28 +286,28 @@ class required {} } : new[] { - // (4,12): error CS9500: Types and aliases cannot not be named 'required'. + // (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 not be named 'required'. + // (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 not be named 'required'. + // (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 not be named 'required'. + // (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 not be named 'required'. + // (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 not be named 'required'. + // (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 not be named 'required'. + // (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 not be named 'required'. + // (35,11): error CS9500: Types and aliases cannot be named 'required'. // class required {} Diagnostic(ErrorCode.ERR_RequiredNameDisallowed, "required").WithLocation(35, 11) } @@ -445,23 +446,48 @@ 01 00 00 00 } [Fact] - public void RequiredMemberAttributeEmitted_OverrideRequiredProperty_MissingRequiredOnOverride() + public void RequiredMemberAttributeEmitted_OverrideRequiredProperty_MissingRequiredOnOverride01() { var comp = CreateCompilationWithRequiredMembers(@" class Base { public virtual required int Prop { get; set; } } -class Dervied : Base +class Derived : Base { public override int Prop { get; set; } } "); comp.VerifyDiagnostics( - // (8,25): error CS9501: 'Dervied.Prop': cannot remove 'required' from 'Base.Prop' when overriding + // (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("Dervied.Prop", "Base.Prop").WithLocation(8, 25) + 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) ); } @@ -843,6 +869,11 @@ 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( @@ -857,7 +888,16 @@ class Derived2 : Base Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeHidden, "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_RequiredMembersCannotBeHidden, "Field").WithArguments("Base.Field", "Derived2.Field").WithLocation(16, 20) + Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeHidden, "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_RequiredMembersCannotBeHidden, "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_RequiredMembersCannotBeHidden, "Prop").WithArguments("Base.Prop", "Derived3.Prop").WithLocation(21, 16) ); } @@ -1056,27 +1096,6 @@ private class PrivateClass ); } - [Fact] - public void RequiredMembersCannotBeExplicitInterfaceImplementations() - { - var comp = CreateCompilationWithRequiredMembers(@" -interface I -{ - int Prop { get; set; } -} -class C : I -{ - required int I.Prop { get; set; } -} -"); - - comp.VerifyDiagnostics( - // (8,20): error CS0106: The modifier 'required' is not valid for this item - // required int I.Prop { get; set; } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "Prop").WithArguments("required").WithLocation(8, 20) - ); - } - [Fact] public void UsingRequiredMemberAttributeExplicitly() { @@ -1093,13 +1112,13 @@ class C "); comp.VerifyDiagnostics( - // (3,2): error CS9504: Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + // (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_ExplicitRequiredMembers, "RequiredMember").WithLocation(3, 2), - // (6,6): error CS9504: Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + // (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_ExplicitRequiredMembers, "RequiredMember").WithLocation(6, 6), - // (8,6): error CS9504: Do not use 'System.Runtime.CompilerSerives.RequiredMembersAttribute'. Use the 'required' keyword on required fields and properties instead. + // (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_ExplicitRequiredMembers, "RequiredMember").WithLocation(8, 6), // (9,16): warning CS0649: Field 'C.Field' is never assigned to, and will always have its default value 0 @@ -1110,4 +1129,42 @@ class C 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) + ); + } } diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs index aa957afb96579..1817d3ab43517 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EENamedTypeSymbol.cs @@ -164,7 +164,7 @@ public override IEnumerable MemberNames get { throw ExceptionUtilities.Unreachable; } } - public override bool HasDeclaredRequiredMembers => throw ExceptionUtilities.Unreachable; + internal override bool HasDeclaredRequiredMembers => throw ExceptionUtilities.Unreachable; public override ImmutableArray GetMembers() { From 5d0fd66ac2f0a4e134735260da96c5e733576bc7 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 28 Jan 2022 15:26:59 -0800 Subject: [PATCH 08/11] Fix up VB tests, only check IL on CoreCLR --- .../Symbol/Symbols/RequiredMembersTests.cs | 23 ++++++++++++++----- .../WellKnownTypeValidationTests.vb | 6 +++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs index 5a8338ec75577..0a566621f0c7e 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -376,7 +376,9 @@ class C Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("C.Field", "0").WithLocation(5, 25) ); - verifier.VerifyTypeIL("C", @" + if (ExecutionConditionUtil.IsCoreClr) + { + verifier.VerifyTypeIL("C", @" .class private auto ansi beforefieldinit C extends [netstandard]System.Object { @@ -443,6 +445,7 @@ 01 00 00 00 } } // end of class C "); + } } [Fact] @@ -510,7 +513,10 @@ class Derived : Base var verifier = CompileAndVerify(comp, sourceSymbolValidator: ValidateRequiredMembersInModule(expectedRequiredMembers)); verifier.VerifyDiagnostics(); - verifier.VerifyTypeIL("Base", @" + + if (ExecutionConditionUtil.IsCoreClr) + { + verifier.VerifyTypeIL("Base", @" .class private auto ansi beforefieldinit Base extends [netstandard]System.Object { @@ -574,7 +580,7 @@ 01 00 00 00 } // end of class Base "); - verifier.VerifyTypeIL("Derived", @" + verifier.VerifyTypeIL("Derived", @" .class private auto ansi beforefieldinit Derived extends Base { @@ -637,6 +643,7 @@ 01 00 00 00 } } // end of class Derived "); + } } [Fact] @@ -662,7 +669,10 @@ class DerivedDerived : Derived var verifier = CompileAndVerify(comp, sourceSymbolValidator: ValidateRequiredMembersInModule(expectedRequiredMembers)); verifier.VerifyDiagnostics(); - verifier.VerifyTypeIL("Base", @" + + if (ExecutionConditionUtil.IsCoreClr) + { + verifier.VerifyTypeIL("Base", @" .class private auto ansi beforefieldinit Base extends [netstandard]System.Object { @@ -720,7 +730,7 @@ .property instance int32 Prop() } // end of class Base "); - verifier.VerifyTypeIL("Derived", @" + verifier.VerifyTypeIL("Derived", @" .class private auto ansi beforefieldinit Derived extends Base { @@ -784,7 +794,7 @@ 01 00 00 00 } // end of class Derived "); - verifier.VerifyTypeIL("DerivedDerived", @" + verifier.VerifyTypeIL("DerivedDerived", @" .class private auto ansi beforefieldinit DerivedDerived extends Derived { @@ -847,6 +857,7 @@ 01 00 00 00 } } // end of class DerivedDerived "); + } } [Fact] diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index 1ef84bdef34dd..4c32b28a689e8 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb @@ -612,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 @@ -841,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, From 23bc3a7e2fc7b6aff506a7135fc405b20afc9eaa Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Thu, 3 Feb 2022 11:44:29 -0800 Subject: [PATCH 09/11] Refactor attribute visitors into a base class with derived visitors. --- .../CSharp/NativeIntegerAttributesVisitor.cs | 219 +---------------- .../CSharp/NullableAttributesVisitor.cs | 192 ++------------- .../Utilities/CSharp/TestAttributesVisitor.cs | 220 ++++++++++++++++++ 3 files changed, 243 insertions(+), 388 deletions(-) create mode 100644 src/Compilers/Test/Utilities/CSharp/TestAttributesVisitor.cs 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/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; + } + } +} From 25a534ffc41e00b6ffffb3e44408c97c8ffccdfd Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Thu, 3 Feb 2022 14:32:30 -0800 Subject: [PATCH 10/11] Address PR feedback. --- .../CSharp/Portable/CSharpResources.resx | 11 +- .../CSharp/Portable/Errors/ErrorCode.cs | 7 +- .../Portable/Symbols/Source/ModifierUtils.cs | 17 +- ...berContainerSymbol_ImplementationChecks.cs | 4 +- .../Symbols/Source/SourceMemberFieldSymbol.cs | 3 +- .../CSharp/Portable/Symbols/Symbol.cs | 2 +- .../Symbols/Wrapped/WrappedFieldSymbol.cs | 2 +- .../Symbols/Wrapped/WrappedPropertySymbol.cs | 2 +- .../Portable/xlf/CSharpResources.cs.xlf | 17 +- .../Portable/xlf/CSharpResources.de.xlf | 17 +- .../Portable/xlf/CSharpResources.es.xlf | 17 +- .../Portable/xlf/CSharpResources.fr.xlf | 17 +- .../Portable/xlf/CSharpResources.it.xlf | 17 +- .../Portable/xlf/CSharpResources.ja.xlf | 17 +- .../Portable/xlf/CSharpResources.ko.xlf | 17 +- .../Portable/xlf/CSharpResources.pl.xlf | 17 +- .../Portable/xlf/CSharpResources.pt-BR.xlf | 17 +- .../Portable/xlf/CSharpResources.ru.xlf | 17 +- .../Portable/xlf/CSharpResources.tr.xlf | 17 +- .../Portable/xlf/CSharpResources.zh-Hans.xlf | 17 +- .../Portable/xlf/CSharpResources.zh-Hant.xlf | 17 +- .../Symbol/Symbols/RequiredMembersTests.cs | 933 ++++++++---------- .../Core/Portable/WellKnownMembers.cs | 2 +- .../CSharp/RequiredMemberAttributesVisitor.cs | 35 + 24 files changed, 611 insertions(+), 628 deletions(-) create mode 100644 src/Compilers/Test/Utilities/CSharp/RequiredMemberAttributesVisitor.cs diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index da6bc6e576a5f..22f1681ce31a0 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6950,13 +6950,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ '{0}': cannot remove 'required' from '{1}' when overriding - + Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. - + 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/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 66c91cf9768c0..548dcc4ff83fe 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2034,8 +2034,9 @@ internal enum ErrorCode ERR_RequiredNameDisallowed = 9500, ERR_OverrideMustHaveRequired = 9501, - ERR_RequiredMembersCannotBeHidden = 9502, - ERR_RequiredMembersCannotBeLessVisibleThanContainingType = 9503, - ERR_ExplicitRequiredMembers = 9504, + ERR_RequiredMemberCannotBeHidden = 9502, + ERR_RequiredMemberCannotBeLessVisibleThanContainingType = 9503, + ERR_ExplicitRequiredMember = 9504, + ERR_RequiredMemberMustBeSettable = 9505, } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs index c1bef4222d7c8..1d70c5a1b6aa2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs @@ -422,12 +422,19 @@ internal static CSDiagnosticInfo CheckAccessibility(DeclarationModifiers modifie } } - if ((modifiers & DeclarationModifiers.Required) != 0 - && symbol.Kind is SymbolKind.Property or SymbolKind.Field - && symbol.DeclaredAccessibility < symbol.ContainingType.DeclaredAccessibility) + if ((modifiers & DeclarationModifiers.Required) != 0) { - // Required member '{0}' cannot be less visible than the containing type '{1}'. - return new CSDiagnosticInfo(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, symbol, symbol.ContainingType); + 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/SourceMemberContainerSymbol_ImplementationChecks.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs index 8c63818713e3c..5c14d9644ef29 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs @@ -715,7 +715,7 @@ private void CheckNewModifier(Symbol symbol, bool isNew, BindingDiagnosticBag di if (hiddenMember.IsRequired()) { // Required member '{0}' cannot be hidden by '{1}'. - diagnostics.Add(ErrorCode.ERR_RequiredMembersCannotBeHidden, symbolLocation, hiddenMember, symbol); + diagnostics.Add(ErrorCode.ERR_RequiredMemberCannotBeHidden, symbolLocation, hiddenMember, symbol); } return; @@ -1424,7 +1424,7 @@ private static void CheckNonOverrideMember( if (hiddenMember.IsRequired()) { // Required member '{0}' cannot be hidden by '{1}'. - diagnostics.Add(ErrorCode.ERR_RequiredMembersCannotBeHidden, hidingMemberLocation, hiddenMember, hidingMember); + diagnostics.Add(ErrorCode.ERR_RequiredMemberCannotBeHidden, hidingMemberLocation, hiddenMember, hidingMember); diagnosticAdded = true; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index 97ae4df10003a..380e2c0c4c317 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -157,7 +157,7 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.Abstract | - DeclarationModifiers.Required; // filtered out later + DeclarationModifiers.Required; // Some of these are filtered out later, when illegal, for better error messages. var errorLocation = new SourceLocation(firstIdentifier); DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers( @@ -197,6 +197,7 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp 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)); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs index 412fd1ddd385a..ea8b6e11a96e2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs @@ -1426,7 +1426,7 @@ internal bool ReportExplicitUseOfReservedAttributes(in DecodeWellKnownAttributeA 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_ExplicitRequiredMembers, arguments.AttributeSyntaxOpt.Location); + diagnostics.Add(ErrorCode.ERR_ExplicitRequiredMember, arguments.AttributeSyntaxOpt.Location); } else { diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedFieldSymbol.cs index 6bed480fef024..166c0264211ce 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedFieldSymbol.cs @@ -205,6 +205,6 @@ public override bool IsStatic } } - internal override bool IsRequired => _underlyingField.IsRequired; + 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 1d2064b7410e8..e9f62600a2a8a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedPropertySymbol.cs @@ -161,7 +161,7 @@ public override bool IsExtern } } - internal override bool IsRequired => _underlyingProperty.IsRequired; + internal sealed override bool IsRequired => _underlyingProperty.IsRequired; internal override ObsoleteAttributeData ObsoleteAttributeData { diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 8db0bdf94260b..a19f085033ea8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -432,7 +432,7 @@ Přístupové objekty {0} a {1} by měly být buď oba jenom pro inicializaci, nebo ani jeden. - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ Relační vzory se nedají použít pro hodnotu Není číslo s plovoucí desetinnou čárkou. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 6fe7da0daa187..fefcc9f658271 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -432,7 +432,7 @@ "init-only" muss entweder für beide oder für keine der Zugriffsmethoden "{0}" und "{1}" festgelegt sein. - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ Relationale Muster dürfen nicht für Gleitkomma-NaNs verwendet werden. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index d294f3d1435b5..dd5d8f16dd59d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -432,7 +432,7 @@ Los descriptores de acceso "{0}" y "{1}" deben ser los dos solo de inicialización o ninguno de ellos - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ No se pueden usar patrones relacionales para un valor NaN de punto flotante. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index b3f957b3c8b48..60d4172ca9027 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -432,7 +432,7 @@ Les accesseurs '{0}' et '{1}' doivent tous deux être initialiseurs uniquement ou ne pas l'être - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ Les modèles relationnels ne peuvent pas être utilisés pour une valeur NaN à virgule flottante. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 5654089ac4547..6bdd6d1fe5a71 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -432,7 +432,7 @@ Il tipo di sola inizializzazione può essere specificato per entrambe le funzioni di accesso '{0}' e '{1}' o per nessuna di esse - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ Non è possibile usare i criteri relazionali per un valore NaN a virgola mobile. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index d9f51e48ceb7c..ffb1a49ea0bb4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -432,7 +432,7 @@ アクセサー '{0}' と '{1}' は、両方 init 専用か、両方そうでないかのいずれかでなければなりません - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ リレーショナル パターンは、浮動小数点の NaN に使用することはできません。 - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index d46ccc519d7b7..23fad227a5071 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -432,7 +432,7 @@ '{0}' 및 '{1}' 접근자는 둘 다 초기값 전용이거나 둘 다 초기값 전용이 아니어야 합니다. - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ 부동 소수점 NaN에는 관계형 패턴을 사용할 수 없습니다. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11428,4 +11433,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 3d91824004e24..56990cd668e6d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -432,7 +432,7 @@ Tylko do inicjowania powinny być obie metody dostępu „{0}” i „{1}” albo żadna z nich - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ Wzorców relacyjnych nie można używać na potrzeby zmiennoprzecinkowej wartości NaN. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 2856c10d04cc2..bb83790d13313 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -432,7 +432,7 @@ Os acessadores '{0}' e '{1}' devem ser somente de inicialização ou nenhum - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ Os padrões relacionais não podem ser usados para um NaN de ponto flutuante. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 7704575a7fd23..86f3b39cb1899 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -432,7 +432,7 @@ Каждый из методов доступа "{0}" и "{1}" должен вызываться только во время инициализации либо ни один из этих методов доступа не должен вызываться таким образом. - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ Реляционные шаблоны не могут использоваться для NaN с плавающей запятой. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 49213e877ee5f..8d4394caf493b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -432,7 +432,7 @@ '{0}' ve '{1}' erişimcilerinin ikisi de yalnızca init olmalıdır ya da ikisi de olmamalıdır - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ İlişkisel desenler, kayan noktalı NaN için kullanılamaz. - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index d06603cbadefc..d8ba71d3cf382 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -432,7 +432,7 @@ 访问器 {0} 和 {1} 应同时为 init-only,或两者都不是 - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ 关系模式可能不能用于浮点 NaN。 - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11434,4 +11439,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 57dc766472c45..03669f0a62a8c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -432,7 +432,7 @@ 存取子 '{0}' 與 '{1}' 不得同時是或不是僅供初始化 - + Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. Do not use 'System.Runtime.CompilerServices.RequiredMemberAttribute'. Use the 'required' keyword on required fields and properties instead. @@ -1097,14 +1097,19 @@ 浮點 NaN 不可使用關聯性模式。 - + Required member '{0}' cannot be hidden by '{1}'. Required member '{0}' cannot be hidden by '{1}'. - - Required member '{0}' cannot be less visible than the containing type '{1}'. - Required member '{0}' cannot be less visible than the containing type '{1}'. + + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + Required member '{0}' cannot be less visible or have a setter less visible than the containing type '{1}'. + + + + Required member '{0}' must be settable. + Required member '{0}' must be settable. @@ -11429,4 +11434,4 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - + \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs index 0a566621f0c7e..31f1d889d22b6 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -1,9 +1,10 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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; @@ -27,18 +28,30 @@ public RequiredMemberAttribute() } "; - private CSharpCompilation CreateCompilationWithRequiredMembers(CSharpTestSource source, CSharpParseOptions? parseOptions = null, CSharpCompilationOptions? options = null, TargetFramework tfm = TargetFramework.NetCoreApp) + 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 Action ValidateRequiredMembersInModule(string[] memberPaths) + 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())); + } } }; } @@ -168,25 +181,27 @@ unsafe struct C [Fact] public void LangVersion() { - var comp = CreateCompilationWithRequiredMembers(@" + string code = @" +#pragma warning disable CS0649 // Field is never assigned class C { internal required int Field; internal required int Prop { get; set; } } -", parseOptions: TestOptions.Regular10); +"; + var comp = CreateCompilationWithRequiredMembers(code, parseOptions: TestOptions.Regular10); comp.VerifyDiagnostics( - // (4,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(4, 27), - // (4,27): warning CS0649: Field 'C.Field' is never assigned to, and will always have its default value 0 - // internal required int Field; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("C.Field", "0").WithLocation(4, 27), // (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(5, 27) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop").WithArguments("required members").WithLocation(6, 27) ); + + comp = CreateCompilationWithRequiredMembers(code, parseOptions: TestOptions.RegularNext); + comp.VerifyDiagnostics(); } [Fact] @@ -217,7 +232,7 @@ class C [CombinatorialData] public void InvalidNames(bool use10) { - var comp = CreateCompilationWithRequiredMembers(@" + string code = @" namespace N1 { struct required {} @@ -253,7 +268,8 @@ namespace N8 { class required {} } -", parseOptions: use10 ? TestOptions.Regular10 : null); +"; + var comp = CreateCompilationWithRequiredMembers(code, parseOptions: use10 ? TestOptions.Regular10 : TestOptions.RegularNext); comp.VerifyDiagnostics( use10 ? @@ -312,6 +328,10 @@ 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] @@ -320,7 +340,7 @@ public void MissingRequiredMemberAttribute() var comp = CreateCompilation(@" class C { - public required int I { get; } + public required int I { get; set; } }"); // (2,7): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.RequiredMemberAttribute..ctor' @@ -336,7 +356,7 @@ public void MissingRequiredMemberAttributeCtor() var comp = CreateCompilation(@" class C { - public required int I { get; } + public required int I { get; set; } } namespace System.Runtime.CompilerServices @@ -369,83 +389,19 @@ class C var expectedRequiredMembers = new[] { "C.Prop", "C.Field" }; - var verifier = CompileAndVerify(comp, sourceSymbolValidator: ValidateRequiredMembersInModule(expectedRequiredMembers)); + 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) ); - - if (ExecutionConditionUtil.IsCoreClr) - { - verifier.VerifyTypeIL("C", @" -.class private auto ansi beforefieldinit C - extends [netstandard]System.Object -{ - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - // Fields - .field private int32 'k__BackingField' - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - .field public int32 Field - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - // Methods - .method public hidebysig specialname - instance int32 get_Prop () cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2050 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld int32 C::'k__BackingField' - IL_0006: ret - } // end of method C::get_Prop - .method public hidebysig specialname - instance void set_Prop ( - int32 'value' - ) cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2058 - // Code size 8 (0x8) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldarg.1 - IL_0002: stfld int32 C::'k__BackingField' - IL_0007: ret - } // end of method C::set_Prop - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed - { - // Method begins at RVA 0x2061 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void [netstandard]System.Object::.ctor() - IL_0006: ret - } // end of method C::.ctor - // Properties - .property instance int32 Prop() - { - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - .get instance int32 C::get_Prop() - .set instance void C::set_Prop(int32) - } -} // end of class C -"); - } } [Fact] @@ -510,140 +466,15 @@ class Derived : Base var expectedRequiredMembers = new[] { "Base.Prop", "Derived.Prop" }; - var verifier = CompileAndVerify(comp, sourceSymbolValidator: ValidateRequiredMembersInModule(expectedRequiredMembers)); - verifier.VerifyDiagnostics(); + var expectedAttributeLayout = @" +[RequiredMember] Base + [RequiredMember] System.Int32 Base.Prop { get; set; } +[RequiredMember] Derived + [RequiredMember] System.Int32 Derived.Prop { get; set; }"; - - if (ExecutionConditionUtil.IsCoreClr) - { - verifier.VerifyTypeIL("Base", @" -.class private auto ansi beforefieldinit Base - extends [netstandard]System.Object -{ - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - // Fields - .field private int32 'k__BackingField' - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Methods - .method public hidebysig specialname newslot virtual - instance int32 get_Prop () cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2050 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld int32 Base::'k__BackingField' - IL_0006: ret - } // end of method Base::get_Prop - .method public hidebysig specialname newslot virtual - instance void set_Prop ( - int32 'value' - ) cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2058 - // Code size 8 (0x8) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldarg.1 - IL_0002: stfld int32 Base::'k__BackingField' - IL_0007: ret - } // end of method Base::set_Prop - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed - { - // Method begins at RVA 0x2061 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void [netstandard]System.Object::.ctor() - IL_0006: ret - } // end of method Base::.ctor - // Properties - .property instance int32 Prop() - { - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - .get instance int32 Base::get_Prop() - .set instance void Base::set_Prop(int32) - } -} // end of class Base -"); - - verifier.VerifyTypeIL("Derived", @" -.class private auto ansi beforefieldinit Derived - extends Base -{ - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - // Fields - .field private int32 'k__BackingField' - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Methods - .method public hidebysig specialname virtual - instance int32 get_Prop () cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2069 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld int32 Derived::'k__BackingField' - IL_0006: ret - } // end of method Derived::get_Prop - .method public hidebysig specialname virtual - instance void set_Prop ( - int32 'value' - ) cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2071 - // Code size 8 (0x8) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldarg.1 - IL_0002: stfld int32 Derived::'k__BackingField' - IL_0007: ret - } // end of method Derived::set_Prop - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed - { - // Method begins at RVA 0x207a - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void Base::.ctor() - IL_0006: ret - } // end of method Derived::.ctor - // Properties - .property instance int32 Prop() - { - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - .get instance int32 Derived::get_Prop() - .set instance void Derived::set_Prop(int32) - } -} // end of class Derived -"); - } + var symbolValidator = ValidateRequiredMembersInModule(expectedRequiredMembers, expectedAttributeLayout); + var verifier = CompileAndVerify(comp, sourceSymbolValidator: symbolValidator, symbolValidator: symbolValidator); + verifier.VerifyDiagnostics(); } [Fact] @@ -666,198 +497,75 @@ class DerivedDerived : Derived var expectedRequiredMembers = new[] { "Derived.Prop", "DerivedDerived.Prop" }; - var verifier = CompileAndVerify(comp, sourceSymbolValidator: ValidateRequiredMembersInModule(expectedRequiredMembers)); - verifier.VerifyDiagnostics(); + 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(); + } - if (ExecutionConditionUtil.IsCoreClr) - { - verifier.VerifyTypeIL("Base", @" -.class private auto ansi beforefieldinit Base - extends [netstandard]System.Object -{ - // Fields - .field private int32 'k__BackingField' - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Methods - .method public hidebysig specialname newslot virtual - instance int32 get_Prop () cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2050 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld int32 Base::'k__BackingField' - IL_0006: ret - } // end of method Base::get_Prop - .method public hidebysig specialname newslot virtual - instance void set_Prop ( - int32 'value' - ) cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2058 - // Code size 8 (0x8) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldarg.1 - IL_0002: stfld int32 Base::'k__BackingField' - IL_0007: ret - } // end of method Base::set_Prop - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed + [Fact] + public void RequiredMemberAttributeEmitted_NestedTypeHasRequired() { - // Method begins at RVA 0x2061 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void [netstandard]System.Object::.ctor() - IL_0006: ret - } // end of method Base::.ctor - // Properties - .property instance int32 Prop() + var comp = CreateCompilationWithRequiredMembers(@" +class Outer +{ + class Inner { - .get instance int32 Base::get_Prop() - .set instance void Base::set_Prop(int32) + public required int Prop { get; set; } + public required int Field; } -} // end of class Base +} "); - verifier.VerifyTypeIL("Derived", @" -.class private auto ansi beforefieldinit Derived - extends Base -{ - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - // Fields - .field private int32 'k__BackingField' - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Methods - .method public hidebysig specialname virtual - instance int32 get_Prop () cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2069 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld int32 Derived::'k__BackingField' - IL_0006: ret - } // end of method Derived::get_Prop - .method public hidebysig specialname virtual - instance void set_Prop ( - int32 'value' - ) cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2071 - // Code size 8 (0x8) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldarg.1 - IL_0002: stfld int32 Derived::'k__BackingField' - IL_0007: ret - } // end of method Derived::set_Prop - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed - { - // Method begins at RVA 0x207a - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void Base::.ctor() - IL_0006: ret - } // end of method Derived::.ctor - // Properties - .property instance int32 Prop() - { - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - .get instance int32 Derived::get_Prop() - .set instance void Derived::set_Prop(int32) + 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) + ); } -} // end of class Derived -"); - verifier.VerifyTypeIL("DerivedDerived", @" -.class private auto ansi beforefieldinit DerivedDerived - extends Derived -{ - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - // Fields - .field private int32 'k__BackingField' - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Methods - .method public hidebysig specialname virtual - instance int32 get_Prop () cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x2082 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld int32 DerivedDerived::'k__BackingField' - IL_0006: ret - } // end of method DerivedDerived::get_Prop - .method public hidebysig specialname virtual - instance void set_Prop ( - int32 'value' - ) cil managed - { - .custom instance void [netstandard]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Method begins at RVA 0x208a - // Code size 8 (0x8) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldarg.1 - IL_0002: stfld int32 DerivedDerived::'k__BackingField' - IL_0007: ret - } // end of method DerivedDerived::set_Prop - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed - { - // Method begins at RVA 0x2093 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void Derived::.ctor() - IL_0006: ret - } // end of method DerivedDerived::.ctor - // Properties - .property instance int32 Prop() + [Fact] + public void RequiredMemberAttributeEmitted_AbstractProperty() { - .custom instance void System.Runtime.CompilerServices.RequiredMemberAttribute::.ctor() = ( - 01 00 00 00 - ) - .get instance int32 DerivedDerived::get_Prop() - .set instance void DerivedDerived::set_Prop(int32) - } -} // end of class DerivedDerived + 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] @@ -890,25 +598,25 @@ class Derived3 : Base comp.VerifyDiagnostics( // (10,20): error CS9502: Required member 'Base.Field' cannot be hidden by 'Derived1.Field'. // public new int Field; // 1 - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeHidden, "Field").WithArguments("Base.Field", "Derived1.Field").WithLocation(10, 20), + 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_RequiredMembersCannotBeHidden, "Prop").WithArguments("Base.Prop", "Derived1.Prop").WithLocation(11, 20), + 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_RequiredMembersCannotBeHidden, "Prop").WithArguments("Base.Prop", "Derived2.Prop").WithLocation(15, 20), + 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_RequiredMembersCannotBeHidden, "Field").WithArguments("Base.Field", "Derived2.Field").WithLocation(16, 20), + 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_RequiredMembersCannotBeHidden, "Field").WithArguments("Base.Field", "Derived3.Field").WithLocation(20, 16), + 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_RequiredMembersCannotBeHidden, "Prop").WithArguments("Base.Prop", "Derived3.Prop").WithLocation(21, 16) + Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeHidden, "Prop").WithArguments("Base.Prop", "Derived3.Prop").WithLocation(21, 16) ); } @@ -921,32 +629,32 @@ public void RequiredMembersMustBeAsVisibleAsContainingType() public class PublicClass { 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; } + 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; - internal required int InternalField; - protected required int ProtectedField; - private protected required int PrivateProtectedField; - private required int PrivateField; + 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; } - private protected required int PrivateProtectedProperty { get; set; } - private required int PrivateProperty { 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; - private protected required int PrivateProtectedField; - private required int PrivateField; + protected required int ProtectedField; // 14 + private protected required int PrivateProtectedField; // 15 + private required int PrivateField; // 16 } internal class Outer { @@ -954,16 +662,16 @@ protected internal class ProtectedInternalClass { 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; } + 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; - protected required int ProtectedField; - private protected required int PrivateProtectedField; - private required int PrivateField; + internal required int InternalField; // 21 + protected required int ProtectedField; // 22 + private protected required int PrivateProtectedField; // 23 + private required int PrivateField; // 24 } protected class ProtectedClass { @@ -971,14 +679,14 @@ protected class ProtectedClass 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; } + 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; - private required int PrivateField; + private protected required int PrivateProtectedField; // 27 + private required int PrivateField; // 28 } private protected class PrivateProtectedClass { @@ -987,13 +695,13 @@ private protected class PrivateProtectedClass 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; } + 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; + private required int PrivateField; // 30 } private class PrivateClass { @@ -1014,99 +722,205 @@ private class PrivateClass "); comp.VerifyDiagnostics( - // (7,37): error CS9503: Required member 'PublicClass.InternalProtectedProperty' cannot be less visible than the containing type 'PublicClass'. - // internal protected required int InternalProtectedProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalProtectedProperty").WithArguments("PublicClass.InternalProtectedProperty", "PublicClass").WithLocation(7, 37), - // (8,27): error CS9503: Required member 'PublicClass.InternalProperty' cannot be less visible than the containing type 'PublicClass'. - // internal required int InternalProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalProperty").WithArguments("PublicClass.InternalProperty", "PublicClass").WithLocation(8, 27), - // (9,28): error CS9503: Required member 'PublicClass.ProtectedProperty' cannot be less visible than the containing type 'PublicClass'. - // protected required int ProtectedProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedProperty").WithArguments("PublicClass.ProtectedProperty", "PublicClass").WithLocation(9, 28), - // (10,36): error CS9503: Required member 'PublicClass.PrivateProtectedProperty' cannot be less visible than the containing type 'PublicClass'. - // private protected required int PrivateProtectedProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("PublicClass.PrivateProtectedProperty", "PublicClass").WithLocation(10, 36), - // (11,26): error CS9503: Required member 'PublicClass.PrivateProperty' cannot be less visible than the containing type 'PublicClass'. - // private required int PrivateProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("PublicClass.PrivateProperty", "PublicClass").WithLocation(11, 26), - // (13,37): error CS9503: Required member 'PublicClass.InternalProtectedField' cannot be less visible than the containing type 'PublicClass'. - // internal protected required int InternalProtectedField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalProtectedField").WithArguments("PublicClass.InternalProtectedField", "PublicClass").WithLocation(13, 37), - // (14,27): error CS9503: Required member 'PublicClass.InternalField' cannot be less visible than the containing type 'PublicClass'. - // internal required int InternalField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalField").WithArguments("PublicClass.InternalField", "PublicClass").WithLocation(14, 27), - // (15,28): error CS9503: Required member 'PublicClass.ProtectedField' cannot be less visible than the containing type 'PublicClass'. - // protected required int ProtectedField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedField").WithArguments("PublicClass.ProtectedField", "PublicClass").WithLocation(15, 28), - // (16,36): error CS9503: Required member 'PublicClass.PrivateProtectedField' cannot be less visible than the containing type 'PublicClass'. - // private protected required int PrivateProtectedField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("PublicClass.PrivateProtectedField", "PublicClass").WithLocation(16, 36), - // (17,26): error CS9503: Required member 'PublicClass.PrivateField' cannot be less visible than the containing type 'PublicClass'. - // private required int PrivateField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("PublicClass.PrivateField", "PublicClass").WithLocation(17, 26), - // (24,28): error CS9503: Required member 'InternalClass.ProtectedProperty' cannot be less visible than the containing type 'InternalClass'. - // protected required int ProtectedProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedProperty").WithArguments("InternalClass.ProtectedProperty", "InternalClass").WithLocation(24, 28), - // (25,36): error CS9503: Required member 'InternalClass.PrivateProtectedProperty' cannot be less visible than the containing type 'InternalClass'. - // private protected required int PrivateProtectedProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("InternalClass.PrivateProtectedProperty", "InternalClass").WithLocation(25, 36), - // (26,26): error CS9503: Required member 'InternalClass.PrivateProperty' cannot be less visible than the containing type 'InternalClass'. - // private required int PrivateProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("InternalClass.PrivateProperty", "InternalClass").WithLocation(26, 26), - // (30,28): error CS9503: Required member 'InternalClass.ProtectedField' cannot be less visible than the containing type 'InternalClass'. - // protected required int ProtectedField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedField").WithArguments("InternalClass.ProtectedField", "InternalClass").WithLocation(30, 28), - // (31,36): error CS9503: Required member 'InternalClass.PrivateProtectedField' cannot be less visible than the containing type 'InternalClass'. - // private protected required int PrivateProtectedField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("InternalClass.PrivateProtectedField", "InternalClass").WithLocation(31, 36), - // (32,26): error CS9503: Required member 'InternalClass.PrivateField' cannot be less visible than the containing type 'InternalClass'. - // private required int PrivateField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("InternalClass.PrivateField", "InternalClass").WithLocation(32, 26), - // (40,31): error CS9503: Required member 'Outer.ProtectedInternalClass.InternalProperty' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. - // internal required int InternalProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalProperty").WithArguments("Outer.ProtectedInternalClass.InternalProperty", "Outer.ProtectedInternalClass").WithLocation(40, 31), - // (41,32): error CS9503: Required member 'Outer.ProtectedInternalClass.ProtectedProperty' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. - // protected required int ProtectedProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedProperty").WithArguments("Outer.ProtectedInternalClass.ProtectedProperty", "Outer.ProtectedInternalClass").WithLocation(41, 32), - // (42,40): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateProtectedProperty' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. - // private protected required int PrivateProtectedProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("Outer.ProtectedInternalClass.PrivateProtectedProperty", "Outer.ProtectedInternalClass").WithLocation(42, 40), - // (43,30): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateProperty' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. - // private required int PrivateProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("Outer.ProtectedInternalClass.PrivateProperty", "Outer.ProtectedInternalClass").WithLocation(43, 30), - // (46,31): error CS9503: Required member 'Outer.ProtectedInternalClass.InternalField' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. - // internal required int InternalField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "InternalField").WithArguments("Outer.ProtectedInternalClass.InternalField", "Outer.ProtectedInternalClass").WithLocation(46, 31), - // (47,32): error CS9503: Required member 'Outer.ProtectedInternalClass.ProtectedField' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. - // protected required int ProtectedField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "ProtectedField").WithArguments("Outer.ProtectedInternalClass.ProtectedField", "Outer.ProtectedInternalClass").WithLocation(47, 32), - // (48,40): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateProtectedField' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. - // private protected required int PrivateProtectedField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("Outer.ProtectedInternalClass.PrivateProtectedField", "Outer.ProtectedInternalClass").WithLocation(48, 40), - // (49,30): error CS9503: Required member 'Outer.ProtectedInternalClass.PrivateField' cannot be less visible than the containing type 'Outer.ProtectedInternalClass'. - // private required int PrivateField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("Outer.ProtectedInternalClass.PrivateField", "Outer.ProtectedInternalClass").WithLocation(49, 30), - // (57,40): error CS9503: Required member 'Outer.ProtectedClass.PrivateProtectedProperty' cannot be less visible than the containing type 'Outer.ProtectedClass'. - // private protected required int PrivateProtectedProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedProperty").WithArguments("Outer.ProtectedClass.PrivateProtectedProperty", "Outer.ProtectedClass").WithLocation(57, 40), - // (58,30): error CS9503: Required member 'Outer.ProtectedClass.PrivateProperty' cannot be less visible than the containing type 'Outer.ProtectedClass'. - // private required int PrivateProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("Outer.ProtectedClass.PrivateProperty", "Outer.ProtectedClass").WithLocation(58, 30), - // (63,40): error CS9503: Required member 'Outer.ProtectedClass.PrivateProtectedField' cannot be less visible than the containing type 'Outer.ProtectedClass'. - // private protected required int PrivateProtectedField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProtectedField").WithArguments("Outer.ProtectedClass.PrivateProtectedField", "Outer.ProtectedClass").WithLocation(63, 40), - // (64,30): error CS9503: Required member 'Outer.ProtectedClass.PrivateField' cannot be less visible than the containing type 'Outer.ProtectedClass'. - // private required int PrivateField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("Outer.ProtectedClass.PrivateField", "Outer.ProtectedClass").WithLocation(64, 30), - // (73,30): error CS9503: Required member 'Outer.PrivateProtectedClass.PrivateProperty' cannot be less visible than the containing type 'Outer.PrivateProtectedClass'. - // private required int PrivateProperty { get; set; } - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateProperty").WithArguments("Outer.PrivateProtectedClass.PrivateProperty", "Outer.PrivateProtectedClass").WithLocation(73, 30), - // (79,30): error CS9503: Required member 'Outer.PrivateProtectedClass.PrivateField' cannot be less visible than the containing type 'Outer.PrivateProtectedClass'. - // private required int PrivateField; - Diagnostic(ErrorCode.ERR_RequiredMembersCannotBeLessVisibleThanContainingType, "PrivateField").WithArguments("Outer.PrivateProtectedClass.PrivateField", "Outer.PrivateProtectedClass").WithLocation(79, 30) + // (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() { @@ -1125,13 +939,13 @@ class C 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_ExplicitRequiredMembers, "RequiredMember").WithLocation(3, 2), + 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_ExplicitRequiredMembers, "RequiredMember").WithLocation(6, 6), + 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_ExplicitRequiredMembers, "RequiredMember").WithLocation(8, 6), + 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) @@ -1178,4 +992,61 @@ public RequiredMemberAttribute() 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) + ); + } } diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index 6b885f3b9c586..74577d8c0ab6a 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3535,7 +3535,7 @@ static WellKnownMembers() 0, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_String, // Return Type - // System_Runtime_CompilerServices_RequiredMembersAttribute__ctor + // System_Runtime_CompilerServices_RequiredMemberAttribute__ctor (byte)MemberFlags.Constructor, // Flags (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_RequiredMemberAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId 0, // Arity 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; + } +} From a192a6abcf39062a1b4674ce543bebcea5b41f5d Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 4 Feb 2022 10:26:58 -0800 Subject: [PATCH 11/11] Add suggested tests. --- .../Symbol/Symbols/RequiredMembersTests.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs index 31f1d889d22b6..7d16b5d73599d 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -1049,4 +1049,44 @@ class C 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(); + } }