diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index 25a71e7c1cf6a..f69ab0f465c8a 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -7136,6 +7136,15 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
'{0}' requires compiler feature '{1}', which is not supported by this version of the C# compiler.
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+
+ Ref returning properties cannot be required.
+
Unexpected keyword 'unchecked'
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index 599214e3c08c2..6a9fcdad67492 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -2089,5 +2089,7 @@ internal enum ErrorCode
ERR_ChainingToSetsRequiredMembersRequiresSetsRequiredMembers = 9510,
ERR_NewConstraintCannotHaveRequiredMembers = 9511,
ERR_UnsupportedCompilerFeature = 9512,
+ WRN_ObsoleteMembersShouldNotBeRequired = 9513,
+ ERR_RefReturningPropertiesCannotBeRequired = 9514,
}
}
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
index d427a18300a58..0d2b3b40fec37 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
@@ -501,6 +501,7 @@ internal static int GetWarningLevel(ErrorCode code)
case ErrorCode.WRN_UseDefViolationThisSupportedVersion:
case ErrorCode.WRN_UnassignedThisAutoPropertySupportedVersion:
case ErrorCode.WRN_UnassignedThisSupportedVersion:
+ case ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired:
return 1;
default:
return 0;
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
index b0c58cadf4247..8bbb62928ab1d 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
@@ -676,7 +676,7 @@ void checkMemberStateOnConstructorExit(MethodSymbol constructor, Symbol member,
return;
}
- if (symbol.IsRequired())
+ if (symbol.IsRequired() && constructor.ShouldCheckRequiredMembers())
{
return;
}
diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs
index f4b635dc89759..4767b0fdbf588 100644
--- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs
@@ -289,6 +289,7 @@ public static bool IsWarning(ErrorCode code)
case ErrorCode.WRN_UseDefViolationThisSupportedVersion:
case ErrorCode.WRN_UnassignedThisAutoPropertySupportedVersion:
case ErrorCode.WRN_UnassignedThisSupportedVersion:
+ case ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired:
return true;
default:
return false;
diff --git a/src/Compilers/CSharp/Portable/Symbols/CompletionPart.cs b/src/Compilers/CSharp/Portable/Symbols/CompletionPart.cs
index db5bf7a0a20f3..c69369a4361fa 100644
--- a/src/Compilers/CSharp/Portable/Symbols/CompletionPart.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/CompletionPart.cs
@@ -49,15 +49,16 @@ internal enum CompletionPart
SynthesizedExplicitImplementations = 1 << 13,
StartMemberChecks = 1 << 14,
FinishMemberChecks = 1 << 15,
- MembersCompleted = 1 << 16, // this should be the last (highest-value) part
+ MembersCompletedChecksStarted = 1 << 16,
+ MembersCompleted = 1 << 17, // this should be the last (highest-value) part
- All = (1 << 17) - 1,
+ All = (1 << 18) - 1,
// This is the work we can do if ForceComplete is scoped to a particular SyntaxTree.
NamedTypeSymbolWithLocationAll = Attributes | StartBaseType | FinishBaseType | StartInterfaces | FinishInterfaces | EnumUnderlyingType |
TypeArguments | TypeParameters | Members | TypeMembers | SynthesizedExplicitImplementations | StartMemberChecks | FinishMemberChecks,
- NamedTypeSymbolAll = NamedTypeSymbolWithLocationAll | MembersCompleted,
+ NamedTypeSymbolAll = NamedTypeSymbolWithLocationAll | MembersCompletedChecksStarted | MembersCompleted,
// For Usings
StartValidatingImports = 1 << 4,
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs
index d3bd015bee4ec..34410c9291708 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs
@@ -244,6 +244,8 @@ internal override LexicalSortKey GetLexicalSortKey()
// so we will keep them the same.
return new LexicalSortKey(this.syntaxReferenceOpt.GetLocation(), this.DeclaringCompilation);
}
+
+ protected override bool HasSetsRequiredMembersImpl => false;
}
private sealed class InvokeMethod : SourceDelegateMethodSymbol
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
index c979a69dc7ecc..1cc6f1f986183 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
@@ -598,6 +598,7 @@ internal override void ForceComplete(SourceLocation? locationOpt, CancellationTo
}
break;
+ case CompletionPart.MembersCompletedChecksStarted:
case CompletionPart.MembersCompleted:
{
ImmutableArray members = this.GetMembersUnordered();
@@ -631,12 +632,22 @@ internal override void ForceComplete(SourceLocation? locationOpt, CancellationTo
}
EnsureFieldDefinitionsNoted();
+ cancellationToken.ThrowIfCancellationRequested();
- // We've completed all members, so we're ready for the PointedAtManagedTypeChecks;
- // proceed to the next iteration.
- state.NotePartComplete(CompletionPart.MembersCompleted);
- break;
+ if (state.NotePartComplete(CompletionPart.MembersCompletedChecksStarted))
+ {
+ var diagnostics = BindingDiagnosticBag.GetInstance();
+ AfterMembersCompletedChecks(diagnostics);
+ AddDeclarationDiagnostics(diagnostics);
+
+ // We've completed all members, so we're ready for the PointedAtManagedTypeChecks;
+ // proceed to the next iteration.
+ var thisThreadCompleted = state.NotePartComplete(CompletionPart.MembersCompleted);
+ Debug.Assert(thisThreadCompleted);
+ diagnostics.Free();
+ }
}
+ break;
case CompletionPart.None:
return;
@@ -1744,6 +1755,10 @@ static bool needsTupleElementNamesAttribute(TypeSymbol type)
}
}
+ protected virtual void AfterMembersCompletedChecks(BindingDiagnosticBag diagnostics)
+ {
+ }
+
private void CheckMemberNamesDistinctFromType(BindingDiagnosticBag diagnostics)
{
foreach (var member in GetMembersAndInitializers().NonTypeMembers)
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs
index aba7d243e2240..49acec15bccbe 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs
@@ -199,7 +199,6 @@ 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/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs
index 65cfa1b1b8289..7b0b8baf70e3e 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs
@@ -1638,5 +1638,42 @@ internal bool IsSimpleProgram
return this.declaration.Declarations.Any(d => d.IsSimpleProgram);
}
}
+
+ protected override void AfterMembersCompletedChecks(BindingDiagnosticBag diagnostics)
+ {
+ base.AfterMembersCompletedChecks(diagnostics);
+
+ // We need to give warnings if Obsolete is applied to any required members and there are constructors where a user would be forced to set that member,
+ // unless:
+ // 1. We're in an obsolete context ourselves, or
+ // 2. All constructors of this type are obsolete or attributed with SetsRequiredMembersAttribute
+ // We don't warn for obsolete required members from base types, as the user either has a warning that they're depending on an obsolete constructor/type
+ // already, or the original author ignored this warning.
+
+ // Obsolete states should have already been calculated by this point in the pipeline.
+ Debug.Assert(ObsoleteKind != ObsoleteAttributeKind.Uninitialized);
+ Debug.Assert(GetMembers().All(m => m.ObsoleteKind != ObsoleteAttributeKind.Uninitialized));
+
+ if (ObsoleteKind != ObsoleteAttributeKind.None
+ || GetMembers().All(m => m is not MethodSymbol { MethodKind: MethodKind.Constructor, ObsoleteKind: ObsoleteAttributeKind.None } method
+ || !method.ShouldCheckRequiredMembers()))
+ {
+ return;
+ }
+
+ foreach (var member in GetMembers())
+ {
+ if (!member.IsRequired())
+ {
+ continue;
+ }
+
+ if (member.ObsoleteKind != ObsoleteAttributeKind.None)
+ {
+ // Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+ diagnostics.Add(ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired, member.Locations[0], member);
+ }
+ }
+ }
}
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
index 9ec1be22c332d..d136fe32d4007 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
@@ -677,6 +677,12 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions,
CheckInitializer(IsAutoProperty, ContainingType.IsInterface, IsStatic, Location, diagnostics);
}
+ if (RefKind != RefKind.None && IsRequired)
+ {
+ // Ref returning properties cannot be required.
+ diagnostics.Add(ErrorCode.ERR_RefReturningPropertiesCannotBeRequired, Location);
+ }
+
if (IsAutoPropertyWithGetAccessor)
{
Debug.Assert(GetMethod is object);
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index 797ba91a87918..1d962dd073c16 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -1207,6 +1207,11 @@
Levá strana přiřazení odkazu musí být lokální proměnná nebo parametr odkazu.
+
+
+ Ref returning properties cannot be required.
+
+ Relační vzory se nedají použít pro hodnotu Není číslo s plovoucí desetinnou čárkou.
@@ -1822,6 +1827,16 @@
Typ s možnou hodnotou null je zaškrtnut hodnotou null a vyvolá se při hodnotě null.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ Parametr {0} musí mít při ukončení hodnotu jinou než null, protože parametr {1} není null.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index a87fa23a6ce66..a20a028ef6e3d 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -1207,6 +1207,11 @@
Die linke Seite einer ref-Zuweisung muss ein lokaler Verweis oder ein Parameter sein.
+
+
+ Ref returning properties cannot be required.
+
+ Relationale Muster dürfen nicht für Gleitkomma-NaNs verwendet werden.
@@ -1822,6 +1827,16 @@
Der Nullable-Typ wurde auf NULL-Werte überprüft und wird bei NULL ausgelöst.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ Der Parameter "{0}" muss beim Beenden einen Wert ungleich NULL aufweisen, weil Parameter "{1}" nicht NULL ist.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index a6ebebc74305b..4d541b16bb4bc 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -1207,6 +1207,11 @@
La parte izquierda de una asignación de referencias debe ser una referencia local o un parámetro.
+
+
+ Ref returning properties cannot be required.
+
+ No se pueden usar patrones relacionales para un valor NaN de punto flotante.
@@ -1822,6 +1827,16 @@
El tipo que acepta valores NULL está activado con valor NULL y se iniciará si es null.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ El parámetro "{0}" debe tener un valor que no sea NULL al salir porque el parámetro "{1}" no es NULL.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index ccc6df16346b9..db0c226e4a872 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -1207,6 +1207,11 @@
La partie gauche d'une assignation par référence doit être une variable locale ou un paramètre ref.
+
+
+ Ref returning properties cannot be required.
+
+ Les modèles relationnels ne peuvent pas être utilisés pour une valeur NaN à virgule flottante.
@@ -1822,6 +1827,16 @@
Le type Nullable est activé pour null et lèvera si null.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ Le paramètre '{0}' doit avoir une valeur non null au moment de la sortie, car le paramètre '{1}' a une valeur non null.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index 4fd1ecc7c49a5..af0758a6db8ce 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -1207,6 +1207,11 @@
La parte sinistra di un'assegnazione ref deve essere un parametro o una variabile locale ref.
+
+
+ Ref returning properties cannot be required.
+
+ Non è possibile usare i criteri relazionali per un valore NaN a virgola mobile.
@@ -1822,6 +1827,16 @@
Il tipo nullable è controllato Null e verrà generato se Null.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ Il parametro '{0}' deve avere un valore non Null quando viene terminato perché il parametro '{1}' è non Null.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index f08227b5ad218..d7ffc804b7376 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -1207,6 +1207,11 @@
ref 代入の左辺は、ref ローカルまたはパラメーターにする必要があります。
+
+
+ Ref returning properties cannot be required.
+
+ リレーショナル パターンは、浮動小数点の NaN に使用することはできません。
@@ -1822,6 +1827,16 @@
Null 許容型は null チェックされており、null の場合はスローされます。
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ パラメーター '{1}' が null 以外であるため、パラメーター '{0}' には、終了時に null 以外の値が含まれている必要があります。
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index f14edbed323cf..df5f883c32b1e 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -1207,6 +1207,11 @@
참조 할당의 왼쪽은 참조 로컬 또는 매개 변수여야 합니다.
+
+
+ Ref returning properties cannot be required.
+
+ 부동 소수점 NaN에는 관계형 패턴을 사용할 수 없습니다.
@@ -1822,6 +1827,16 @@
nullable 형식은 Null로 확인되며 Null이면 throw됩니다.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ 매개 변수 '{1}'이(가) null이 아니므로 매개 변수 '{0}'은(는) 종료할 때 null이 아닌 값을 가져야 합니다.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index 0536e8a94722b..328b46dd83543 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -1207,6 +1207,11 @@
Lewa strona przypisania odwołania musi być odwołaniem lokalnym lub parametrem.
+
+
+ Ref returning properties cannot be required.
+
+ Wzorców relacyjnych nie można używać na potrzeby zmiennoprzecinkowej wartości NaN.
@@ -1822,6 +1827,16 @@
Typ dopuszczający wartość null jest sprawdzony przy użyciu wartości null i będzie widoczny w przypadku wartości null.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ Parametr „{0}” musi mieć wartość inną niż null podczas kończenia działania, ponieważ parametr „{1}” ma wartość inną niż null.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index 90eaa5624ee2a..40d44160e793a 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -1207,6 +1207,11 @@
O lado esquerdo da atribuição ref precisa ser um parâmetro ou local ref.
+
+
+ Ref returning properties cannot be required.
+
+ Os padrões relacionais não podem ser usados para um NaN de ponto flutuante.
@@ -1822,6 +1827,16 @@
O tipo anulável é verificado como nulo e será lançado se for nulo.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ O parâmetro '{0}' precisa ter um valor não nulo durante a saída porque o parâmetro '{1}' não é nulo.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 59d56531c7bda..b604a5ff09381 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -1207,6 +1207,11 @@
Левая часть выражения назначения ссылки должна быть локальной ссылкой или параметром.
+
+
+ Ref returning properties cannot be required.
+
+ Реляционные шаблоны не могут использоваться для NaN с плавающей запятой.
@@ -1822,6 +1827,16 @@
Для типа, допускающего значение NULL, выполнена проверка значения NULL. Он будет выдаваться, если ему присвоено значение NULL.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ При выходе параметр "{0}" должен иметь значение, отличное от NULL, так как параметр "{1}" имеет значение, отличное от NULL.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index 67c005075a5bf..58d282a6171f8 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -1207,6 +1207,11 @@
ref atamasının sol tarafı, yerel ref veya parametresi olmalıdır.
+
+
+ Ref returning properties cannot be required.
+
+ İlişkisel desenler, kayan noktalı NaN için kullanılamaz.
@@ -1822,6 +1827,16 @@
Boş değer atanabilir tip null denetimlidir ve null ise atılır.
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ '{1}' parametresi null olmadığından '{0}' parametresi çıkış yaparken null olmayan bir değere sahip olmalıdır.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index 16ec3b986d101..0a7543bfb358b 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -1207,6 +1207,11 @@
ref 赋值左侧必须为 ref 本地函数或参数。
+
+
+ Ref returning properties cannot be required.
+
+ 关系模式可能不能用于浮点 NaN。
@@ -1822,6 +1827,16 @@
对可以为 null 的类型进行了 null 检查,如果为 null,将抛出异常。
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ 退出时参数“{0}”必须具有非 null 值,因为参数“{1}”是非 null。
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index 2f8aa17dc5122..01020f0f4fccb 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -1207,6 +1207,11 @@
參考指派的左側必須為參考本機或參數。
+
+
+ Ref returning properties cannot be required.
+
+ 浮點 NaN 不可使用關聯性模式。
@@ -1822,6 +1827,16 @@
可為 Null 的類型會檢查是否為 Null,若為 Null,則會擲回。
+
+
+ Required member '{0}' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+
+
+
+
+ Members attributed with 'ObsoleteAttribute' should not be required unless the containing type is obsolete or all constructors are obsolete.
+
+ 因為參數 '{1}' 不是 null,所以參數 '{0}' 在結束時必須具有非 Null 值。
diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs
index 7ddb94dca75a5..f70fdac7f2d69 100644
--- a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs
+++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs
@@ -1242,63 +1242,186 @@ public void RefReturningProperties()
class C
{
private int i;
- public required ref int Prop => ref i;
+ public required ref int Prop1 => ref i;
+ public required ref readonly int Prop2 => ref i;
}
");
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)
+ // (5,29): error CS9505: Required member 'C.Prop1' must be settable.
+ // public required ref int Prop1 => ref i;
+ Diagnostic(ErrorCode.ERR_RequiredMemberMustBeSettable, "Prop1").WithArguments("C.Prop1").WithLocation(5, 29),
+ // (5,29): error CS9514: Ref returning properties cannot be required.
+ // public required ref int Prop1 => ref i;
+ Diagnostic(ErrorCode.ERR_RefReturningPropertiesCannotBeRequired, "Prop1").WithLocation(5, 29),
+ // (6,38): error CS9505: Required member 'C.Prop2' must be settable.
+ // public required ref readonly int Prop2 => ref i;
+ Diagnostic(ErrorCode.ERR_RequiredMemberMustBeSettable, "Prop2").WithArguments("C.Prop2").WithLocation(6, 38),
+ // (6,38): error CS9514: Ref returning properties cannot be required.
+ // public required ref readonly int Prop2 => ref i;
+ Diagnostic(ErrorCode.ERR_RefReturningPropertiesCannotBeRequired, "Prop2").WithLocation(6, 38)
);
}
- [Fact]
- public void UnsettableMembers()
- {
- var comp = CreateCompilationWithRequiredMembers(@"
+ [Theory]
+ [InlineData("internal")]
+ [InlineData("internal protected")]
+ [InlineData("protected")]
+ [InlineData("private protected")]
+ [InlineData("private")]
+ public void UnsettableMembers(string setterAccessibility)
+ {
+ var comp = CreateCompilationWithRequiredMembers($$"""
#pragma warning disable CS0649 // Unassigned field
-class C
+public class C
{
public required readonly int Field;
public required int Prop1 { get; }
- public required int Prop2 { get; protected set; }
+ public required int Prop2 { get; {{setterAccessibility}} set; }
}
-");
+""");
comp.VerifyDiagnostics(
- // (5,34): error CS9505: Required member 'C.Field' must be settable.
+ // (4,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.
+ Diagnostic(ErrorCode.ERR_RequiredMemberMustBeSettable, "Field").WithArguments("C.Field").WithLocation(4, 34),
+ // (5,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),
- // PROTOTYPE(req): Better error message?
- // (7,25): error CS9503: Required member 'C.Prop2' cannot be less visible or have a setter less visible than the containing type 'C'.
- // public required int Prop2 { get; protected set; }
- Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Prop2").WithArguments("C.Prop2", "C").WithLocation(7, 25)
+ Diagnostic(ErrorCode.ERR_RequiredMemberMustBeSettable, "Prop1").WithArguments("C.Prop1").WithLocation(5, 25),
+ // (6,25): error CS9503: Required member 'C.Prop2' cannot be less visible or have a setter less visible than the containing type 'C'.
+ // public required int Prop2 { get; private set; }
+ Diagnostic(ErrorCode.ERR_RequiredMemberCannotBeLessVisibleThanContainingType, "Prop2").WithArguments("C.Prop2", "C").WithLocation(6, 25)
);
}
[Fact]
- public void ObsoleteMember()
+ public void ObsoleteMember_NoObsoleteContext()
{
- 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; }
-}
-");
+ 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; }
+ }
+ """);
+
+ comp.VerifyDiagnostics(
+ // (6,25): warning CS9513: Required member 'C.Field' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+ // public required int Field;
+ Diagnostic(ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired, "Field").WithArguments("C.Field").WithLocation(6, 25),
+ // (8,25): warning CS9513: Required member 'C.Prop1' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+ // public required int Prop1 { get; set; }
+ Diagnostic(ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired, "Prop1").WithArguments("C.Prop1").WithLocation(8, 25)
+ );
+ }
+
+ [Fact]
+ public void ObsoleteMember_NoObsoleteContext_Struct()
+ {
+ var comp = CreateCompilationWithRequiredMembers("""
+ using System;
+ #pragma warning disable CS0649 // Unassigned field
+ struct S
+ {
+ [Obsolete]
+ public required int Field;
+ [Obsolete]
+ public required int Prop1 { get; set; }
+ }
+ """);
+
+ comp.VerifyDiagnostics(
+ // (6,25): warning CS9513: Required member 'S.Field' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+ // public required int Field;
+ Diagnostic(ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired, "Field").WithArguments("S.Field").WithLocation(6, 25),
+ // (8,25): warning CS9513: Required member 'S.Prop1' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+ // public required int Prop1 { get; set; }
+ Diagnostic(ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired, "Prop1").WithArguments("S.Prop1").WithLocation(8, 25)
+ );
+ }
+
+ [Fact]
+ public void ObsoleteMember_ObsoleteContext()
+ {
+ var comp = CreateCompilationWithRequiredMembers("""
+ using System;
+ #pragma warning disable CS0649 // Unassigned field
+ [Obsolete]
+ class C
+ {
+ [Obsolete]
+ public required int Field;
+ [Obsolete]
+ public required int Prop1 { get; set; }
+ }
+ """);
+
+ comp.VerifyDiagnostics();
+ }
+
+ [Fact]
+ public void ObsoleteMember_ObsoleteOrSetsRequiredMembersConstructors_01()
+ {
+ var comp = CreateCompilationWithRequiredMembers("""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ #pragma warning disable CS0649 // Unassigned field
+ class C
+ {
+ [Obsolete]
+ public C() { }
+ [SetsRequiredMembers]
+ public C(int i) { }
+
+ [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 ObsoleteMember_ObsoleteOrSetsRequiredMembersConstructors_02()
+ {
+ var comp = CreateCompilationWithRequiredMembers("""
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ #pragma warning disable CS0649 // Unassigned field
+ class C
+ {
+ [Obsolete]
+ public C() { }
+ [SetsRequiredMembers]
+ public C(int i) { }
+
+ public C(bool b) { }
+
+ [Obsolete]
+ public required int Field;
+ [Obsolete]
+ public required int Prop1 { get; set; }
+ }
+
+ """);
+
+ comp.VerifyDiagnostics(
+ // (14,25): warning CS9513: Required member 'C.Field' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+ // public required int Field;
+ Diagnostic(ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired, "Field").WithArguments("C.Field").WithLocation(14, 25),
+ // (16,25): warning CS9513: Required member 'C.Prop1' should not be attributed with 'ObsoleteAttribute' unless the containing type is obsolete or all constructors are obsolete.
+ // public required int Prop1 { get; set; }
+ Diagnostic(ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired, "Prop1").WithArguments("C.Prop1").WithLocation(16, 25)
+ );
+ }
+
[Fact]
public void ReadonlyPropertiesAndStructs()
{
@@ -3668,7 +3791,7 @@ public class Base
public string Prop2 { get; set; } = null!;
[SetsRequiredMembers]
- protected Base() {}
+ protected Base() {} // 1
}
public class Derived : Base
@@ -3676,26 +3799,29 @@ public class Derived : Base
public required string Prop3 { get; set; }
public string Prop4 { get; set; }
- public Derived() : base()
+ public Derived() : base() // 2
{
Prop1.ToString();
Prop2.ToString();
- Prop3.ToString(); // 1
- Prop4.ToString(); // 2
+ Prop3.ToString(); // 3
+ Prop4.ToString(); // 4
}
}
""";
var comp = CreateCompilationWithRequiredMembers(code);
comp.VerifyDiagnostics(
+ // (9,15): warning CS8618: Non-nullable property 'Prop1' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
+ // protected Base() {} // 1
+ Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Base").WithArguments("property", "Prop1").WithLocation(9, 15),
// (17,24): error CS9510: This constructor must add 'SetsRequiredMembers' because it chains to a constructor that has that attribute.
- // public Derived() : base()
+ // public Derived() : base() // 2
Diagnostic(ErrorCode.ERR_ChainingToSetsRequiredMembersRequiresSetsRequiredMembers, "base").WithLocation(17, 24),
// (21,9): warning CS8602: Dereference of a possibly null reference.
- // Prop3.ToString(); // 1
+ // Prop3.ToString(); // 3
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "Prop3").WithLocation(21, 9),
// (22,9): warning CS8602: Dereference of a possibly null reference.
- // Prop4.ToString(); // 2
+ // Prop4.ToString(); // 4
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "Prop4").WithLocation(22, 9)
);
}
@@ -3737,6 +3863,9 @@ public Derived() : this(0)
var comp = CreateCompilationWithRequiredMembers(code);
comp.VerifyDiagnostics(
+ // (17,12): warning CS8618: Non-nullable property 'Prop3' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
+ // public Derived(int unused) : base()
+ Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Derived").WithArguments("property", "Prop3").WithLocation(17, 12),
// (22,24): error CS9510: This constructor must add 'SetsRequiredMembers' because it chains to a constructor that has that attribute.
// public Derived() : this(0)
Diagnostic(ErrorCode.ERR_ChainingToSetsRequiredMembersRequiresSetsRequiredMembers, "this").WithLocation(22, 24)
diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs
index cc92c05f00e5a..c2f329a272eb1 100644
--- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs
@@ -272,6 +272,7 @@ public void WarningLevel_2()
case ErrorCode.WRN_CallerArgumentExpressionAttributeSelfReferential:
case ErrorCode.WRN_NullCheckedHasDefaultNull:
case ErrorCode.WRN_NullCheckingOnNullableType:
+ case ErrorCode.WRN_ObsoleteMembersShouldNotBeRequired:
Assert.Equal(1, ErrorFacts.GetWarningLevel(errorCode));
break;
case ErrorCode.WRN_MainIgnored:
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb b/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb
index c3a29d918b151..12411f11b7d10 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb
@@ -33,7 +33,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Friend Shared Function GetObsoleteDataFromMetadata(token As EntityHandle, containingModule As PEModuleSymbol) As ObsoleteAttributeData
Dim obsoleteAttributeData As ObsoleteAttributeData = Nothing
' ignoreByRefLikeMarker := False, since VB does not support ref-like types
- ' PROTOTYPE(req): Determine what support will be added for VB
+ ' https://github.com/dotnet/roslyn/issues/61435: Determine what support will be added for VB
obsoleteAttributeData = containingModule.Module.TryGetDeprecatedOrExperimentalOrObsoleteAttribute(token, New MetadataDecoder(containingModule), ignoreByRefLikeMarker:=False, ignoreRequiredMemberMarker:=False)
Debug.Assert(obsoleteAttributeData Is Nothing OrElse Not obsoleteAttributeData.IsUninitialized)
Return obsoleteAttributeData