From 3eb86dad3b3997690fb69459df45ca648b942107 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 1 Oct 2024 10:56:15 -0700 Subject: [PATCH 1/7] Add warning when property has a backing field but a manually implemented accessor does not use it --- .../CSharp/Portable/CSharpResources.resx | 6 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../CSharp/Portable/Errors/ErrorFacts.cs | 2 + .../Generated/ErrorFacts.Generated.cs | 1 + .../Symbols/Source/SourcePropertySymbol.cs | 37 +- .../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 + .../CSharp/Test/Emit3/FieldKeywordTests.cs | 372 ++++++++++++++++-- .../Test/Syntax/Diagnostics/DiagnosticTest.cs | 1 + 20 files changed, 515 insertions(+), 35 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 05651836cd261..701591d6cb7ac 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -8002,4 +8002,10 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Non-nullable property must contain a non-null value when exiting constructor. Consider adding the 'required' modifier, or declaring the property as nullable, or adding '[field: MaybeNull, AllowNull]' attributes. + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + Property accessor should use the backing 'field' because the other accessor is using it. + diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 7c07bb82d271e..35c47c1677b78 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2346,6 +2346,7 @@ internal enum ErrorCode ERR_PartialPropertyDuplicateInitializer = 9263, WRN_UninitializedNonNullableBackingField = 9264, + WRN_AccessorDoesNotUseBackingField = 9265, // Note: you will need to do the following after adding errors: // 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs) diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 4c8a7e03fa39c..da0e90a7f9af6 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -560,6 +560,7 @@ internal static int GetWarningLevel(ErrorCode code) case ErrorCode.WRN_PartialPropertySignatureDifference: case ErrorCode.WRN_FieldIsAmbiguous: case ErrorCode.WRN_UninitializedNonNullableBackingField: + case ErrorCode.WRN_AccessorDoesNotUseBackingField: return 1; default: return 0; @@ -2460,6 +2461,7 @@ or ErrorCode.ERR_CannotApplyOverloadResolutionPriorityToOverride or ErrorCode.ERR_CannotApplyOverloadResolutionPriorityToMember or ErrorCode.ERR_PartialPropertyDuplicateInitializer or ErrorCode.WRN_UninitializedNonNullableBackingField + or ErrorCode.WRN_AccessorDoesNotUseBackingField => false, }; #pragma warning restore CS8524 // The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs index 1d3dab8bda75f..55237f1372b07 100644 --- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs @@ -341,6 +341,7 @@ public static bool IsWarning(ErrorCode code) case ErrorCode.WRN_PartialPropertySignatureDifference: case ErrorCode.WRN_FieldIsAmbiguous: case ErrorCode.WRN_UninitializedNonNullableBackingField: + case ErrorCode.WRN_AccessorDoesNotUseBackingField: return true; default: return false; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index a76fc7bd75edf..d56b00c263ccb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -43,7 +43,8 @@ private static SourcePropertySymbol Create( out bool isExpressionBodied, out bool hasGetAccessorImplementation, out bool hasSetAccessorImplementation, - out bool usesFieldKeyword, + out bool getterUsesFieldKeyword, + out bool setterUsesFieldKeyword, out var getSyntax, out var setSyntax); @@ -73,7 +74,7 @@ private static SourcePropertySymbol Create( string? aliasQualifierOpt; string memberName = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(binder, explicitInterfaceSpecifier, name, diagnostics, out explicitInterfaceType, out aliasQualifierOpt); - return new SourcePropertySymbol( + var symbol = new SourcePropertySymbol( containingType, syntax, hasGetAccessor: getSyntax != null || isExpressionBodied, @@ -87,10 +88,27 @@ private static SourcePropertySymbol Create( hasAutoPropertySet: hasAutoPropertySet, isExpressionBodied: isExpressionBodied, accessorsHaveImplementation: accessorsHaveImplementation, - usesFieldKeyword: usesFieldKeyword, + usesFieldKeyword: getterUsesFieldKeyword || setterUsesFieldKeyword, memberName, location, diagnostics); + + AccessorDeclarationSyntax? accessorToBlame = null; + if (hasSetAccessorImplementation && !setterUsesFieldKeyword && (hasAutoPropertyGet || getterUsesFieldKeyword)) + { + accessorToBlame = setSyntax; + } + else if (hasGetAccessorImplementation && !getterUsesFieldKeyword && (hasAutoPropertySet || setterUsesFieldKeyword)) + { + accessorToBlame = getSyntax; + } + + if (accessorToBlame is not null) + { + diagnostics.Add(ErrorCode.WRN_AccessorDoesNotUseBackingField, accessorToBlame.Keyword, [accessorToBlame.Keyword.ValueText, symbol]); + } + + return symbol; } private SourcePropertySymbol( @@ -211,7 +229,8 @@ private static void GetAccessorDeclarations( out bool isExpressionBodied, out bool hasGetAccessorImplementation, out bool hasSetAccessorImplementation, - out bool usesFieldKeyword, + out bool getterUsesFieldKeyword, + out bool setterUsesFieldKeyword, out AccessorDeclarationSyntax? getSyntax, out AccessorDeclarationSyntax? setSyntax) { @@ -222,7 +241,8 @@ private static void GetAccessorDeclarations( if (!isExpressionBodied) { - usesFieldKeyword = false; + getterUsesFieldKeyword = false; + setterUsesFieldKeyword = false; hasGetAccessorImplementation = false; hasSetAccessorImplementation = false; foreach (var accessor in syntax.AccessorList!.Accessors) @@ -234,6 +254,7 @@ private static void GetAccessorDeclarations( { getSyntax = accessor; hasGetAccessorImplementation = hasImplementation(accessor); + getterUsesFieldKeyword = containsFieldKeyword(accessor); } else { @@ -246,6 +267,7 @@ private static void GetAccessorDeclarations( { setSyntax = accessor; hasSetAccessorImplementation = hasImplementation(accessor); + setterUsesFieldKeyword = containsFieldKeyword(accessor); } else { @@ -263,8 +285,6 @@ private static void GetAccessorDeclarations( default: throw ExceptionUtilities.UnexpectedValue(accessor.Kind()); } - - usesFieldKeyword = usesFieldKeyword || containsFieldKeyword(accessor); } } else @@ -272,7 +292,8 @@ private static void GetAccessorDeclarations( var body = GetArrowExpression(syntax); hasGetAccessorImplementation = body is object; hasSetAccessorImplementation = false; - usesFieldKeyword = body is { } && containsFieldKeyword(body); + getterUsesFieldKeyword = body is { } && containsFieldKeyword(body); + setterUsesFieldKeyword = false; Debug.Assert(hasGetAccessorImplementation); // it's not clear how this even parsed as a property if it has no accessor list and no arrow expression. } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 5c13a2167ade1..63635c8778d73 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2662,6 +2662,16 @@ {0} není platná operace šíření v jazyce C# + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. Operátor „&“ by se neměl používat u parametrů nebo místních proměnných v asynchronních metodách. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 4ce31788a2fd0..0080e753709f5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2662,6 +2662,16 @@ {0} ist kein gültiger C#-Überfüllungsvorgang. + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. Der Operator '&' sollte nicht für Parameter oder lokale Variablen in asynchronen Methoden verwendet werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index f87588211bdb3..5e7835b49081f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2662,6 +2662,16 @@ {0} no es una operación de propagación de C# válida + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. El operador ''&'' no debe usarse en parámetros o variables locales en métodos asincrónicos. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 7f264ffb34f6d..aebaf7c2fab9e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2662,6 +2662,16 @@ {0} n’est pas une opération de propagation C# valide + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. L’opérateur '&' ne doit pas être utilisé sur les paramètres ou les variables locales dans les méthodes asynchrones. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 81c7fb0a57c80..61ca3a049bf03 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2662,6 +2662,16 @@ {0} non è un'operazione estensione C# valida + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. L'operatore '&' non deve essere usato su parametri o variabili locali in metodi asincroni. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 30221bfe16639..36d3fe0726386 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2662,6 +2662,16 @@ {0} は有効な C# 分散演算ではありません + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. '&' 演算子は、非同期メソッドのパラメーターまたはローカル変数では使用できません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index cc1ba0d19a634..e86e5fe14d7c3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2662,6 +2662,16 @@ {0}은(는) 유효한 C# 확산 작업이 아닙니다. + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. '&' 연산자는 비동기 메서드의 매개 변수 또는 지역 변수에 사용하면 안 됩니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 427ba4bb942f6..b4f7631a5b43b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2662,6 +2662,16 @@ {0} nie jest prawidłową operacją rozłożenia w języku C# + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. Operator „&” nie powinien być używany w parametrach ani zmiennych lokalnych w metodach asynchronicznych. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index c011342fc3001..a39a9b1a2dff2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2662,6 +2662,16 @@ {0} não é uma operação de espalhamento C# válida + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. O operador '&' não deve ser usado em parâmetros ou variáveis locais em métodos assíncronos. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index cd87210637a7a..ece7b0a0962e8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2662,6 +2662,16 @@ {0} не является допустимой операцией расширения C# + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. Оператор "&" не следует использовать для параметров или локальных переменных в асинхронных методах. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 4ce08d9e9aafe..31c803c03529f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2662,6 +2662,16 @@ {0}, geçerli bir C# yayma işlemi değil + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. '&' işleci, zaman uyumsuz yöntemlerdeki parametrelerde veya yerel değişkenlerde kullanılmamalı. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 75c6a80b057cd..653d52550bf54 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2662,6 +2662,16 @@ {0} 不是有效的 C# 分布操作 + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. '&' 运算符不应用于异步方法中的参数或局部变量。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 9f26bc783732b..d0ef09b50e80c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2662,6 +2662,16 @@ {0} 不是有效的 C# spread 作業 + + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + + + + Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use the backing 'field' because the other accessor is using it. + + The '&' operator should not be used on parameters or local variables in async methods. '&' 運算子不應該用於非同步方法中的參數或區域變數。 diff --git a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs index 6e7364596a931..b4a3e27fccda1 100644 --- a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs @@ -181,6 +181,78 @@ static void Main() """)); } + [Fact] + public void MigratingToFieldKeyword_01() + { + string source = """ + class C + { + object _field; + object P1 + { + get { return _field; } // 1 + set { field = value; } + } + + object P2 + { + get { return field; } + set { _field = value; } // 2 + } + + object P3 + { + get { return _field; } + set { _field = value; } + } + + object P4 + { + get { return field; } + set { field = value; } + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // get { return _field; } // 1 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(6, 9), + // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. + // set { _field = value; } // 2 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(13, 9)); + } + + [Fact] + public void MigratingToFieldKeyword_02() + { + string source = """ + class C + { + object _field; + object P1 + { + get { return _field; } // 1 + set; + } + + object P2 + { + get; + set { _field = value; } // 2 + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // get { return _field; } // 1 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(6, 9), + // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. + // set { _field = value; } // 2 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(13, 9)); + } + [Fact] public void FieldReference_01() { @@ -197,6 +269,9 @@ object P """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (6,9): warning CS9265: The 'get' accessor of property 'C.P' should use the backing 'field' because the other accessor is using it. + // get { return _other.field; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P").WithLocation(6, 9), // (6,29): error CS1061: 'C' does not contain a definition for 'field' and no accessible extension method 'field' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) // get { return _other.field; } Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "field").WithArguments("C", "field").WithLocation(6, 29)); @@ -217,6 +292,9 @@ C P """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (5,9): warning CS9265: The 'get' accessor of property 'C.P' should use the backing 'field' because the other accessor is using it. + // get { return null; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P").WithLocation(5, 9), // (6,29): error CS1061: 'C' does not contain a definition for 'field' and no accessible extension method 'field' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) // set { field = value.field; } Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "field").WithArguments("C", "field").WithLocation(6, 29)); @@ -247,6 +325,9 @@ int P """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (6,9): warning CS9265: The 'set' accessor of property 'C.P' should use the backing 'field' because the other accessor is using it. + // set { _ = this is { field: 0 }; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P").WithLocation(6, 9), // (6,29): error CS0117: 'C' does not contain a definition for 'field' // set { _ = this is { field: 0 }; } Diagnostic(ErrorCode.ERR_NoSuchMember, "field").WithArguments("C", "field").WithLocation(6, 29)); @@ -1108,6 +1189,12 @@ class C // (8,20): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // object P1 { [A(field)] get { return null; } set { } } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(8, 20), + // (8,49): warning CS9265: The 'set' accessor of property 'B.P1' should use the backing 'field' because the other accessor is using it. + // object P1 { [A(field)] get { return null; } set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.P1").WithLocation(8, 49), + // (9,17): warning CS9265: The 'get' accessor of property 'B.P2' should use the backing 'field' because the other accessor is using it. + // object P2 { get { return null; } [A(field)] set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P2").WithLocation(9, 17), // (9,41): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // object P2 { get { return null; } [A(field)] set { } } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(9, 41), @@ -1116,7 +1203,10 @@ class C Diagnostic(ErrorCode.WRN_FieldIsAmbiguous, "field").WithArguments("preview").WithLocation(14, 20), // (14,20): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // object P3 { [A(field)] get { return null; } set { } } - Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(14, 20)); + Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(14, 20), + // (14,49): warning CS9265: The 'set' accessor of property 'C.P3' should use the backing 'field' because the other accessor is using it. + // object P3 { [A(field)] get { return null; } set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P3").WithLocation(14, 49)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); @@ -1194,6 +1284,12 @@ static void ReportMember(MemberInfo member) // (18,37): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. // public static object P5 { get; [field: A(5)] set; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, param, return").WithLocation(18, 37), + // (20,81): warning CS9265: The 'set' accessor of property 'B.Q2' should use the backing 'field' because the other accessor is using it. + // [field: A(2)][field: A(-2)] public static object Q2 { get { return field; } set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.Q2").WithLocation(20, 81), + // (21,60): warning CS9265: The 'init' accessor of property 'B.Q3' should use the backing 'field' because the other accessor is using it. + // [field: A(3)] public object Q3 { get { return field; } init { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "B.Q3").WithLocation(21, 60), // (22,25): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. // public object Q4 { [field: A(4)] get => field; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, return").WithLocation(22, 25), @@ -1282,6 +1378,18 @@ static void ReportMember(MemberInfo member) C.k__BackingField: System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.ObsoleteAttribute, """); verifier.VerifyDiagnostics( + // (5,63): warning CS9265: The 'set' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // [Obsolete] public static object P1 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P1").WithLocation(5, 63), + // (6,63): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. + // [field: Obsolete] public static object P2 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(6, 63), + // (7,56): warning CS9265: The 'set' accessor of property 'C.P3' should use the backing 'field' because the other accessor is using it. + // [Obsolete] public object P3 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P3").WithLocation(7, 56), + // (8,56): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // [field: Obsolete] public object P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(8, 56), // (15,13): warning CS0612: 'C.P1' is obsolete // _ = C.P1; Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "C.P1").WithArguments("C.P1").WithLocation(15, 13), @@ -1327,7 +1435,10 @@ static void Main() targetFramework: TargetFramework.Net80, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(1, 2, 3, 4, 0, 6, 7, 9)")); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // public static int P4 { get => field; set { } } = 4; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42)); verifier.VerifyIL("C..cctor", """ { // Code size 56 (0x38) @@ -1416,7 +1527,10 @@ static void Main() targetFramework: TargetFramework.Net80, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(1, 2, 3, 4, 0, 6, 7, 9)")); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // public static int P4 { get => field; set { } } = 4; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42)); verifier.VerifyIL("C..cctor", """ { // Code size 56 (0x38) @@ -1477,7 +1591,10 @@ static void Main() targetFramework: GetTargetFramework(useInit), verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(useInit, "(1, 2, 3, 4, 0, 6, 7, 9)")); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (7,35): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // public int P4 { get => field; set { } } = 4; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P4").WithLocation(7, 35)); verifier.VerifyIL("C..ctor", """ { // Code size 71 (0x47) @@ -1582,7 +1699,10 @@ static void Main() targetFramework: GetTargetFramework(useInit), verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(useInit, "(1, 2, 3, 4, 0, 6, 7, 9)")); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (7,35): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // public int P4 { get => field; set { } } = 4; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P4").WithLocation(7, 35)); verifier.VerifyIL("C..ctor", """ { // Code size 65 (0x41) @@ -1684,6 +1804,9 @@ interface I // (7,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P4 { get => field; set { } } = 4; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P4").WithLocation(7, 16), + // (7,35): warning CS9265: The 'set' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. + // public int P4 { get => field; set { } } = 4; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "I.P4").WithLocation(7, 35), // (8,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P5 { get => 0; set; } = 5; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P5").WithLocation(8, 16), @@ -1809,7 +1932,10 @@ static void Main() targetFramework: TargetFramework.Net80, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(0, 0, 3, 0, 0, 6, 0, 9)")); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (7,42): warning CS9265: The 'set' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. + // public static int P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P4").WithLocation(7, 42)); var comp = (CSharpCompilation)verifier.Compilation; var containingType = comp.GetMember("I"); @@ -1874,6 +2000,9 @@ interface I // (6,16): error CS0525: Interfaces cannot contain instance fields // int P4 { get => field; set { } } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P4").WithLocation(6, 16), + // (6,35): warning CS9265: The 'set' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. + // int P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "I.P4").WithLocation(6, 35), // (7,16): error CS0525: Interfaces cannot contain instance fields // int P5 { get => 0; set; } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P5").WithLocation(7, 16), @@ -2001,7 +2130,10 @@ static void Main() targetFramework: TargetFramework.Net80, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(1, 2, 3, 0, 0, 6, 0, 9)")); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // public static int P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42)); verifier.VerifyIL("C..cctor", """ { // Code size 56 (0x38) @@ -2121,7 +2253,10 @@ static void Main() targetFramework: GetTargetFramework(useInit), verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(useInit, "(1, 2, 3, 0, 0, 6, 0, 9)")); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (27,35): warning CS9265: The 'set' accessor of property 'C4.P4' should use the backing 'field' because the other accessor is using it. + // public int P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C4.P4").WithLocation(27, 35)); if (typeKind == "class") { verifier.VerifyIL("C1..ctor(int)", $$""" @@ -3437,6 +3572,9 @@ static B() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (6,50): warning CS9265: The 'set' accessor of property 'A.P5' should use the backing 'field' because the other accessor is using it. + // public static int P5 { get => field; private set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "A.P5").WithLocation(6, 50), // (13,9): error CS0272: The property or indexer 'A.P1' cannot be used in this context because the set accessor is inaccessible // P1 = 1; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "P1").WithArguments("A.P1").WithLocation(13, 9), @@ -3484,6 +3622,12 @@ public B() """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( + // (8,43): warning CS9265: The 'set' accessor of property 'A.P5' should use the backing 'field' because the other accessor is using it. + // public int P5 { get => field; private set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "A.P5").WithLocation(8, 43), + // (9,43): warning CS9265: The 'init' accessor of property 'A.P6' should use the backing 'field' because the other accessor is using it. + // public int P6 { get => field; private init { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "A.P6").WithLocation(9, 43), // (17,9): error CS0272: The property or indexer 'A.P1' cannot be used in this context because the set accessor is inaccessible // P1 = 1; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "P1").WithArguments("A.P1").WithLocation(17, 9), @@ -3588,7 +3732,10 @@ static void Main() } """; var verifier = CompileAndVerify(source, expectedOutput: "(1, 2, 3, 0)"); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // public static int P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42)); verifier.VerifyIL("C..cctor", """ { // Code size 39 (0x27) @@ -4175,7 +4322,13 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use var comp = CreateCompilation(source, targetFramework: GetTargetFramework(useInit)); if (useInit) { - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (6,40): warning CS9265: The 'init' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // object P4 { get => field; init { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.P4").WithLocation(6, 40), + // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // object P8 { get => null; init { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26)); } else if (useReadOnlyType) { @@ -4183,9 +4336,15 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use // (5,21): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P3 { get => field; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P3").WithLocation(5, 21), + // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // object P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(6, 40), // (8,21): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P6 { get => null; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P6").WithLocation(8, 21), + // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // object P8 { get => null; set { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), // (11,21): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P9 { get; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P9").WithLocation(11, 21), @@ -4202,9 +4361,15 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use // (5,21): error CS8659: Auto-implemented property 'S.P3' cannot be marked 'readonly' because it has a 'set' accessor. // readonly object P3 { get => field; set; } Diagnostic(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, "P3").WithArguments("S.P3").WithLocation(5, 21), + // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // readonly object P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(6, 40), // (8,21): error CS8659: Auto-implemented property 'S.P6' cannot be marked 'readonly' because it has a 'set' accessor. // readonly object P6 { get => null; set; } Diagnostic(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, "P6").WithArguments("S.P6").WithLocation(8, 21), + // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // readonly object P8 { get => null; set { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), // (11,21): error CS8659: Auto-implemented property 'S.P9' cannot be marked 'readonly' because it has a 'set' accessor. // readonly object P9 { get; set; } Diagnostic(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, "P9").WithArguments("S.P9").WithLocation(11, 21), @@ -4217,7 +4382,13 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use } else { - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // object P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(6, 40), + // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // object P8 { get => null; set { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26)); } var actualMembers = comp.GetMember("S").GetMembers().OfType().Select(f => $"{f.ToTestDisplayString()}: {f.IsReadOnly}"); var expectedMembers = new[] @@ -4267,9 +4438,15 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (3,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P3 { readonly get => field; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P3").WithLocation(3, 12), + // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // object P4 { readonly get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), // (5,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P6 { readonly get => null; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P6").WithLocation(5, 12), + // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // object P8 { readonly get => null; set { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26), // (8,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P9 { readonly get; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P9").WithLocation(8, 12), @@ -4286,12 +4463,18 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (3,49): error CS8658: Auto-implemented 'set' accessor 'S.P3.set' cannot be marked 'readonly'. // object P3 { get => field; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P3.set").WithLocation(3, 49), + // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // object P4 { get => field; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), // (5,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P6").WithLocation(5, 12), // (5,48): error CS8658: Auto-implemented 'set' accessor 'S.P6.set' cannot be marked 'readonly'. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P6.set").WithLocation(5, 48), + // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // object P8 { get => null; readonly set { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26), // (8,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P9 { get; readonly set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P9").WithLocation(8, 12), @@ -4307,7 +4490,13 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) { if (useReadOnlyOnGet) { - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // object P4 { readonly get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), + // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // object P8 { readonly get => null; set { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26)); } else { @@ -4315,9 +4504,15 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (3,49): error CS8658: Auto-implemented 'set' accessor 'S.P3.set' cannot be marked 'readonly'. // object P3 { get => field; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P3.set").WithLocation(3, 49), + // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // object P4 { get => field; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), // (5,48): error CS8658: Auto-implemented 'set' accessor 'S.P6.set' cannot be marked 'readonly'. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P6.set").WithLocation(5, 48), + // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // object P8 { get => null; readonly set { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26), // (8,40): error CS8658: Auto-implemented 'set' accessor 'S.P9.set' cannot be marked 'readonly'. // object P9 { get; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P9.set").WithLocation(8, 40), @@ -4553,7 +4748,10 @@ struct S Diagnostic(ErrorCode.ERR_DuplicatePropertyReadOnlyMods, "Q5").WithArguments("S.Q5").WithLocation(12, 12), // (12,49): error CS8903: 'init' accessors cannot be marked 'readonly'. Mark 'S.Q5' readonly instead. // object Q5 { readonly get => field; readonly init { } } - Diagnostic(ErrorCode.ERR_InitCannotBeReadonly, "init").WithArguments("S.Q5").WithLocation(12, 49)); + Diagnostic(ErrorCode.ERR_InitCannotBeReadonly, "init").WithArguments("S.Q5").WithLocation(12, 49), + // (12,49): warning CS9265: The 'init' accessor of property 'S.Q5' should use the backing 'field' because the other accessor is using it. + // object Q5 { readonly get => field; readonly init { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.Q5").WithLocation(12, 49)); } else { @@ -4587,7 +4785,10 @@ struct S Diagnostic(ErrorCode.ERR_ReadOnlyModMissingAccessor, "Q2").WithArguments("S.Q2").WithLocation(9, 12), // (12,12): error CS8661: Cannot specify 'readonly' modifiers on both accessors of property or indexer 'S.Q5'. Instead, put a 'readonly' modifier on the property itself. // object Q5 { readonly get => field; readonly set { } } - Diagnostic(ErrorCode.ERR_DuplicatePropertyReadOnlyMods, "Q5").WithArguments("S.Q5").WithLocation(12, 12)); + Diagnostic(ErrorCode.ERR_DuplicatePropertyReadOnlyMods, "Q5").WithArguments("S.Q5").WithLocation(12, 12), + // (12,49): warning CS9265: The 'set' accessor of property 'S.Q5' should use the backing 'field' because the other accessor is using it. + // object Q5 { readonly get => field; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.Q5").WithLocation(12, 49)); } var actualMembers = comp.GetMember("S").GetMembers().OfType().Select(f => $"{f.ToTestDisplayString()}: {f.IsReadOnly}"); var expectedMembers = new[] @@ -4779,12 +4980,18 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (7,25): error CS8145: Auto-implemented properties cannot return by reference // ref object P5 { get => ref field; set { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P5").WithLocation(7, 25), + // (7,48): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // ref object P5 { get => ref field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 48), // (7,48): error CS8147: Properties which return by reference cannot have set accessors // ref object P5 { get => ref field; set { } } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "set").WithLocation(7, 48), // (8,25): error CS8145: Auto-implemented properties cannot return by reference // ref object P6 { get => ref field; init { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P6").WithLocation(8, 25), + // (8,48): warning CS9265: The 'init' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // ref object P6 { get => ref field; init { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.P6").WithLocation(8, 48), // (8,48): error CS8147: Properties which return by reference cannot have set accessors // ref object P6 { get => ref field; init { } } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "init").WithLocation(8, 48), @@ -4803,12 +5010,18 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (12,25): error CS8145: Auto-implemented properties cannot return by reference // ref object PC { get => throw null; set { _ = field; } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PC").WithLocation(12, 25), + // (12,30): warning CS9265: The 'get' accessor of property 'S.PC' should use the backing 'field' because the other accessor is using it. + // ref object PC { get => throw null; set { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.PC").WithLocation(12, 30), // (12,49): error CS8147: Properties which return by reference cannot have set accessors // ref object PC { get => throw null; set { _ = field; } } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "set").WithLocation(12, 49), // (13,25): error CS8145: Auto-implemented properties cannot return by reference // ref object PD { get => throw null; init { _ = field; } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PD").WithLocation(13, 25), + // (13,30): warning CS9265: The 'get' accessor of property 'S.PD' should use the backing 'field' because the other accessor is using it. + // ref object PD { get => throw null; init { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.PD").WithLocation(13, 30), // (13,49): error CS8147: Properties which return by reference cannot have set accessors // ref object PD { get => throw null; init { _ = field; } } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "init").WithLocation(13, 49), @@ -4888,6 +5101,9 @@ public void RefReturning_02(bool useStruct, bool useRefReadOnly) // (6,32): error CS8145: Auto-implemented properties cannot return by reference // static ref object P5 { get => ref field; set { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P5").WithLocation(6, 32), + // (6,55): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // static ref object P5 { get => ref field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(6, 55), // (6,55): error CS8147: Properties which return by reference cannot have set accessors // static ref object P5 { get => ref field; set { } } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "set").WithLocation(6, 55), @@ -4900,6 +5116,9 @@ public void RefReturning_02(bool useStruct, bool useRefReadOnly) // (9,32): error CS8145: Auto-implemented properties cannot return by reference // static ref object PC { get => throw null; set { _ = field; } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PC").WithLocation(9, 32), + // (9,37): warning CS9265: The 'get' accessor of property 'S.PC' should use the backing 'field' because the other accessor is using it. + // static ref object PC { get => throw null; set { _ = field; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.PC").WithLocation(9, 37), // (9,56): error CS8147: Properties which return by reference cannot have set accessors // static ref object PC { get => throw null; set { _ = field; } } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "set").WithLocation(9, 56), @@ -4943,7 +5162,10 @@ struct S Diagnostic(ErrorCode.ERR_RefReadonly, "field").WithLocation(4, 33), // (5,45): error CS1605: Cannot use 'field' as a ref or out value because it is read-only // object P3 { readonly get { return F(ref field); } set { } } - Diagnostic(ErrorCode.ERR_RefReadonlyLocal, "field").WithArguments("field").WithLocation(5, 45)); + Diagnostic(ErrorCode.ERR_RefReadonlyLocal, "field").WithArguments("field").WithLocation(5, 45), + // (5,55): warning CS9265: The 'set' accessor of property 'S.P3' should use the backing 'field' because the other accessor is using it. + // object P3 { readonly get { return F(ref field); } set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P3").WithLocation(5, 55)); } [Fact] @@ -4960,7 +5182,10 @@ struct S } """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (5,54): warning CS9265: The 'set' accessor of property 'S.P3' should use the backing 'field' because the other accessor is using it. + // object P3 { readonly get { return F(in field); } set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P3").WithLocation(5, 54)); } [Fact] @@ -4977,7 +5202,10 @@ struct S } """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (5,51): warning CS9265: The 'set' accessor of property 'S.P3' should use the backing 'field' because the other accessor is using it. + // object P3 { readonly get { return F(field); } set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P3").WithLocation(5, 51)); } [Fact] @@ -5002,6 +5230,9 @@ struct S """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( + // (5,40): warning CS9265: The 'set' accessor of property 'S.P3' should use the backing 'field' because the other accessor is using it. + // object P3 { readonly get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P3").WithLocation(5, 40), // (9,15): error CS0206: A non ref-returning property or indexer may not be used as an out or ref value // F(ref P1); Diagnostic(ErrorCode.ERR_RefProperty, "P1").WithLocation(9, 15), @@ -7043,7 +7274,19 @@ class C comp.VerifyEmitDiagnostics( // (3,25): error CS8051: Auto-implemented properties must have get accessors. // object P02 { set; } - Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, setter).WithLocation(3, 25)); + Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, setter).WithLocation(3, 25), + // (12,39): warning CS9265: The 'set' accessor of property 'C.P23' should use the backing 'field' because the other accessor is using it. + // object P23 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P23").WithLocation(12, 39), + // (17,25): warning CS9265: The 'get' accessor of property 'C.P34' should use the backing 'field' because the other accessor is using it. + // object P34 { get => null; set { field = value; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P34").WithLocation(17, 25), + // (20,47): warning CS9265: The 'set' accessor of property 'C.P43' should use the backing 'field' because the other accessor is using it. + // object P43 { get { return field; } set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P43").WithLocation(20, 47), + // (25,25): warning CS9265: The 'get' accessor of property 'C.P54' should use the backing 'field' because the other accessor is using it. + // object P54 { get { return null; } set { field = value; } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P54").WithLocation(25, 25)); } [Theory] @@ -7113,6 +7356,12 @@ class B2 : A """; comp = CreateCompilation([sourceA, sourceB2], targetFramework: targetFramework); comp.VerifyEmitDiagnostics( + // (3,47): warning CS9265: The 'set' accessor of property 'B2.P1' should use the backing 'field' because the other accessor is using it. + // public override object P1 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P1").WithLocation(3, 47), + // (4,47): warning CS9265: The 'set' accessor of property 'B2.P2' should use the backing 'field' because the other accessor is using it. + // public override object P2 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P2").WithLocation(4, 47), // (4,47): error CS0546: 'B2.P2.set': cannot override because 'A.P2' does not have an overridable set accessor // public override object P2 { get => field; set { } } Diagnostic(ErrorCode.ERR_NoSetToOverride, setter).WithArguments($"B2.P2.{setter}", "A.P2").WithLocation(4, 47), @@ -7121,7 +7370,10 @@ class B2 : A Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, setter).WithLocation(5, 32), // (5,33): error CS0545: 'B2.P3.get': cannot override because 'A.P3' does not have an overridable get accessor // public override object P3 { get => field; set { } } - Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("B2.P3.get", "A.P3").WithLocation(5, 33)); + Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("B2.P3.get", "A.P3").WithLocation(5, 33), + // (5,47): warning CS9265: The 'set' accessor of property 'B2.P3' should use the backing 'field' because the other accessor is using it. + // public override object P3 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P3").WithLocation(5, 47)); string sourceB3 = $$""" class B3 : A @@ -7237,12 +7489,21 @@ class B2 : A """; comp = CreateCompilation([sourceA, sourceB2], targetFramework: targetFramework); comp.VerifyEmitDiagnostics( + // (3,47): warning CS9265: The 'set' accessor of property 'B2.P1' should use the backing 'field' because the other accessor is using it. + // public override object P1 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P1").WithLocation(3, 47), + // (4,47): warning CS9265: The 'set' accessor of property 'B2.P2' should use the backing 'field' because the other accessor is using it. + // public override object P2 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P2").WithLocation(4, 47), // (4,47): error CS0546: 'B2.P2.set': cannot override because 'A.P2' does not have an overridable set accessor // public override object P2 { get => field; set { } } Diagnostic(ErrorCode.ERR_NoSetToOverride, setter).WithArguments($"B2.P2.{setter}", "A.P2").WithLocation(4, 47), // (5,33): error CS0545: 'B2.P3.get': cannot override because 'A.P3' does not have an overridable get accessor // public override object P3 { get => field; set { } } - Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("B2.P3.get", "A.P3").WithLocation(5, 33)); + Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("B2.P3.get", "A.P3").WithLocation(5, 33), + // (5,47): warning CS9265: The 'set' accessor of property 'B2.P3' should use the backing 'field' because the other accessor is using it. + // public override object P3 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P3").WithLocation(5, 47)); string sourceB3 = $$""" class B3 : A @@ -7344,7 +7605,16 @@ class B4 : A comp.VerifyEmitDiagnostics( // (5,32): error CS8051: Auto-implemented properties must have get accessors. // public virtual object P3 { set; } - Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, setter).WithLocation(5, 32)); + Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, setter).WithLocation(5, 32), + // (21,42): warning CS9265: The 'set' accessor of property 'B2.P1' should use the backing 'field' because the other accessor is using it. + // public new object P1 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P1").WithLocation(21, 42), + // (22,42): warning CS9265: The 'set' accessor of property 'B2.P2' should use the backing 'field' because the other accessor is using it. + // public new object P2 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P2").WithLocation(22, 42), + // (23,42): warning CS9265: The 'set' accessor of property 'B2.P3' should use the backing 'field' because the other accessor is using it. + // public new object P3 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P3").WithLocation(23, 42)); } [Theory] @@ -7540,7 +7810,10 @@ class C Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "TypedReference").WithArguments("System.TypedReference").WithLocation(7, 12), // (8,5): error CS0610: Field or property cannot be of type 'ArgIterator' // ArgIterator Q2 { get { return field; } set { } } - Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "ArgIterator").WithArguments("System.ArgIterator").WithLocation(8, 5)); + Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "ArgIterator").WithArguments("System.ArgIterator").WithLocation(8, 5), + // (8,44): warning CS9265: The 'set' accessor of property 'C.Q2' should use the backing 'field' because the other accessor is using it. + // ArgIterator Q2 { get { return field; } set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.Q2").WithLocation(8, 44)); } [Theory] @@ -8267,7 +8540,13 @@ partial interface I targetFramework: TargetFramework.Net80); if (useStatic) { - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (5,46): warning CS9265: The 'set' accessor of property 'I.P3' should use the backing 'field' because the other accessor is using it. + // static partial object P3 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P3").WithLocation(5, 46), + // (6,32): warning CS9265: The 'get' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. + // static partial object P4 { get => null; set { field = value; } } = 4; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P4").WithLocation(6, 32)); } else { @@ -8281,9 +8560,15 @@ partial interface I // (5,27): error CS8053: Instance properties in interfaces cannot have initializers. // partial object P3 { get; set; } = 3; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P3").WithLocation(5, 27), + // (5,46): warning CS9265: The 'set' accessor of property 'I.P3' should use the backing 'field' because the other accessor is using it. + // partial object P3 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P3").WithLocation(5, 46), // (6,27): error CS8053: Instance properties in interfaces cannot have initializers. // partial object P4 { get => null; set { field = value; } } = 4; - Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P4").WithLocation(6, 27)); + Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P4").WithLocation(6, 27), + // (6,32): warning CS9265: The 'get' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. + // partial object P4 { get => null; set { field = value; } } = 4; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P4").WithLocation(6, 32)); } var containingType = comp.GetMember("I"); @@ -9017,7 +9302,13 @@ partial struct S switch (useReadOnlyDefinition, useReadOnlyImplementation) { case (false, false): - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // partial object P8 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), + // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // partial object P9 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P9").WithLocation(11, 48)); break; case (false, true): comp.VerifyEmitDiagnostics( @@ -9045,6 +9336,12 @@ partial struct S // (10,34): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P8 { readonly get => field; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "get").WithLocation(10, 34), + // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // partial object P8 { readonly get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), + // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // partial object P9 { get => field; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P9").WithLocation(11, 48), // (11,48): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P9 { get => field; readonly set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "set").WithLocation(11, 48)); @@ -9081,6 +9378,12 @@ partial struct S // (10,34): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P8 { get => field; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "get").WithLocation(10, 34), + // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // partial object P8 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), + // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // partial object P9 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P9").WithLocation(11, 48), // (11,48): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P9 { get => field; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "set").WithLocation(11, 48)); @@ -9092,7 +9395,13 @@ partial struct S Diagnostic(ErrorCode.ERR_ReadOnlyModMissingAccessor, "P3").WithArguments("S.P3").WithLocation(5, 20), // (6,20): error CS8664: 'S.P4': 'readonly' can only be used on accessors if the property or indexer has both a get and a set accessor // partial object P4 { readonly set; } - Diagnostic(ErrorCode.ERR_ReadOnlyModMissingAccessor, "P4").WithArguments("S.P4").WithLocation(6, 20)); + Diagnostic(ErrorCode.ERR_ReadOnlyModMissingAccessor, "P4").WithArguments("S.P4").WithLocation(6, 20), + // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // partial object P8 { readonly get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), + // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // partial object P9 { get => field; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P9").WithLocation(11, 48)); break; } @@ -9157,6 +9466,9 @@ partial class B // (3,35): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // partial object P1 { [A(field)] get { return null; } } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(3, 35), + // (4,32): warning CS9265: The 'get' accessor of property 'B.P2' should use the backing 'field' because the other accessor is using it. + // partial object P2 { get { return null; } [A(field)] set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P2").WithLocation(4, 32), // (4,56): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // partial object P2 { get { return null; } [A(field)] set { } } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(4, 56), @@ -9296,9 +9608,15 @@ partial class B // (3,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored. // [field: A] partial object P1 { get; set; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(3, 6), + // (4,50): warning CS9265: The 'set' accessor of property 'B.P2' should use the backing 'field' because the other accessor is using it. + // partial object P2 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.P2").WithLocation(4, 50), // (6,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored. // [field: A] partial object Q1 { get => null; set { } } - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(6, 6)); + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(6, 6), + // (7,50): warning CS9265: The 'set' accessor of property 'B.Q2' should use the backing 'field' because the other accessor is using it. + // [field: A] partial object Q2 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.Q2").WithLocation(7, 50)); var containingType = comp.GetMember("B"); var actualFields = containingType.GetMembers().OfType().ToImmutableArray(); diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs index 47c197cb03303..641790d62e02f 100644 --- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs +++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs @@ -434,6 +434,7 @@ public void WarningLevel_2() case ErrorCode.INF_TooManyBoundLambdas: case ErrorCode.WRN_FieldIsAmbiguous: case ErrorCode.WRN_UninitializedNonNullableBackingField: + case ErrorCode.WRN_AccessorDoesNotUseBackingField: Assert.Equal(1, ErrorFacts.GetWarningLevel(errorCode)); break; case ErrorCode.WRN_InvalidVersionFormat: From 5a8104ac5b83ddb3f5ef27893d29d75760eba201 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 1 Oct 2024 16:03:39 -0700 Subject: [PATCH 2/7] Adjust check. Update more tests. --- .../Symbols/Source/SourcePropertySymbol.cs | 25 +- .../Test/Emit3/Attributes/AttributeTests.cs | 3 + .../Attributes/AttributeTests_Locations.cs | 57 ++-- .../CSharp/Test/Emit3/FieldKeywordTests.cs | 275 ++++++++++++++++-- .../DefaultInterfaceImplementationTests.cs | 30 +- .../Symbol/Symbols/PartialPropertiesTests.cs | 11 +- .../Test/Symbol/Symbols/SymbolErrorTests.cs | 12 +- 7 files changed, 349 insertions(+), 64 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index d56b00c263ccb..ca3cf9e382356 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -93,19 +93,22 @@ private static SourcePropertySymbol Create( location, diagnostics); - AccessorDeclarationSyntax? accessorToBlame = null; - if (hasSetAccessorImplementation && !setterUsesFieldKeyword && (hasAutoPropertyGet || getterUsesFieldKeyword)) + if (binder.Compilation.IsFeatureEnabled(MessageID.IDS_FeatureFieldKeyword)) { - accessorToBlame = setSyntax; - } - else if (hasGetAccessorImplementation && !getterUsesFieldKeyword && (hasAutoPropertySet || setterUsesFieldKeyword)) - { - accessorToBlame = getSyntax; - } + AccessorDeclarationSyntax? accessorToBlame = null; + if (hasSetAccessorImplementation && !setterUsesFieldKeyword && (hasAutoPropertyGet || getterUsesFieldKeyword)) + { + accessorToBlame = setSyntax; + } + else if (hasGetAccessorImplementation && !getterUsesFieldKeyword && (hasAutoPropertySet || setterUsesFieldKeyword)) + { + accessorToBlame = getSyntax; + } - if (accessorToBlame is not null) - { - diagnostics.Add(ErrorCode.WRN_AccessorDoesNotUseBackingField, accessorToBlame.Keyword, [accessorToBlame.Keyword.ValueText, symbol]); + if (accessorToBlame is not null) + { + diagnostics.Add(ErrorCode.WRN_AccessorDoesNotUseBackingField, accessorToBlame.Keyword, [accessorToBlame.Keyword.ValueText, symbol]); + } } return symbol; diff --git a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs index 620867a4028d8..5a6a2f49e8a88 100644 --- a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs @@ -2396,6 +2396,9 @@ public class Test // (6,21): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. // public int P { [field: A] get => throw null; set => throw null; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, return").WithLocation(6, 21), + // (6,50): warning CS9265: The 'set' accessor of property 'Test.P' should use the backing 'field' because the other accessor is using it. + // public int P { [field: A] get => throw null; set => throw null; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "Test.P").WithLocation(6, 50), // (7,22): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. // public int P2 { [field: A] get; set; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, return").WithLocation(7, 22), diff --git a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs index b12d41deb17c3..3684f2d7c6330 100644 --- a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs +++ b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs @@ -632,24 +632,36 @@ int Goo } "; CreateCompilation(source).VerifyDiagnostics( + // (25,9): warning CS9265: The 'set' accessor of property 'C.Goo' should use the backing 'field' because the other accessor is using it. + // set { } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.Goo").WithLocation(25, 9), // (12,10): warning CS0657: 'assembly' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "assembly").WithArguments("assembly", "method, return"), + // [assembly: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "assembly").WithArguments("assembly", "method, return").WithLocation(12, 10), // (13,10): warning CS0657: 'module' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "module").WithArguments("module", "method, return"), + // [module: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "module").WithArguments("module", "method, return").WithLocation(13, 10), // (14,10): warning CS0657: 'type' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "type").WithArguments("type", "method, return"), + // [type: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "type").WithArguments("type", "method, return").WithLocation(14, 10), // (16,10): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, return"), + // [field: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, return").WithLocation(16, 10), // (17,10): warning CS0657: 'property' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "property").WithArguments("property", "method, return"), + // [property: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "property").WithArguments("property", "method, return").WithLocation(17, 10), // (18,10): warning CS0657: 'event' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "event").WithArguments("event", "method, return"), + // [event: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "event").WithArguments("event", "method, return").WithLocation(18, 10), // (20,10): warning CS0657: 'param' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "param").WithArguments("param", "method, return"), + // [param: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "param").WithArguments("param", "method, return").WithLocation(20, 10), // (21,10): warning CS0657: 'typevar' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "typevar").WithArguments("typevar", "method, return"), + // [typevar: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "typevar").WithArguments("typevar", "method, return").WithLocation(21, 10), // (22,10): warning CS0658: 'delegate' is not a recognized attribute location. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_InvalidAttributeLocation, "delegate").WithArguments("delegate", "method, return")); + // [delegate: A] + Diagnostic(ErrorCode.WRN_InvalidAttributeLocation, "delegate").WithArguments("delegate", "method, return").WithLocation(22, 10)); } [Fact] @@ -684,22 +696,33 @@ int Goo } "; CreateCompilation(source).VerifyDiagnostics( + // (11,9): warning CS9265: The 'get' accessor of property 'C.Goo' should use the backing 'field' because the other accessor is using it. + // get { return 0; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Goo").WithLocation(11, 9), // (14,10): warning CS0657: 'assembly' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "assembly").WithArguments("assembly", "method, param, return"), + // [assembly: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "assembly").WithArguments("assembly", "method, param, return").WithLocation(14, 10), // (15,10): warning CS0657: 'module' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "module").WithArguments("module", "method, param, return"), + // [module: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "module").WithArguments("module", "method, param, return").WithLocation(15, 10), // (16,10): warning CS0657: 'type' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "type").WithArguments("type", "method, param, return"), + // [type: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "type").WithArguments("type", "method, param, return").WithLocation(16, 10), // (18,10): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, param, return"), + // [field: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, param, return").WithLocation(18, 10), // (19,10): warning CS0657: 'property' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "property").WithArguments("property", "method, param, return"), + // [property: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "property").WithArguments("property", "method, param, return").WithLocation(19, 10), // (20,10): warning CS0657: 'event' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "event").WithArguments("event", "method, param, return"), + // [event: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "event").WithArguments("event", "method, param, return").WithLocation(20, 10), // (23,10): warning CS0657: 'typevar' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "typevar").WithArguments("typevar", "method, param, return"), + // [typevar: A] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "typevar").WithArguments("typevar", "method, param, return").WithLocation(23, 10), // (24,10): warning CS0658: 'delegate' is not a recognized attribute location. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. - Diagnostic(ErrorCode.WRN_InvalidAttributeLocation, "delegate").WithArguments("delegate", "method, param, return")); + // [delegate: A] + Diagnostic(ErrorCode.WRN_InvalidAttributeLocation, "delegate").WithArguments("delegate", "method, param, return").WithLocation(24, 10)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs index b4a3e27fccda1..31a68ae315f49 100644 --- a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs @@ -884,9 +884,15 @@ interface I // (5,12): error CS0525: Interfaces cannot contain instance fields // object Q3 { get; set { } } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "Q3").WithLocation(5, 12), + // (5,22): warning CS9265: The 'set' accessor of property 'I.Q3' should use the backing 'field' because the other accessor is using it. + // object Q3 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, useInit ? "init" : "set").WithArguments(useInit ? "init" : "set", "I.Q3").WithLocation(5, 22), // (6,12): error CS0525: Interfaces cannot contain instance fields // object Q4 { get { return null; } set ; } - Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "Q4").WithLocation(6, 12)); + Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "Q4").WithLocation(6, 12), + // (6,17): warning CS9265: The 'get' accessor of property 'I.Q4' should use the backing 'field' because the other accessor is using it. + // object Q4 { get { return null; } set ; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.Q4").WithLocation(6, 17)); } var containingType = comp.GetMember("I"); @@ -1438,7 +1444,13 @@ static void Main() verifier.VerifyDiagnostics( // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. // public static int P4 { get => field; set { } } = 4; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42), + // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // public static int P5 { get => 0; set; } = 5; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28), + // (10,33): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. + // public static int P7 { get; set { } } = 7; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P7").WithLocation(10, 33)); verifier.VerifyIL("C..cctor", """ { // Code size 56 (0x38) @@ -1530,7 +1542,13 @@ static void Main() verifier.VerifyDiagnostics( // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. // public static int P4 { get => field; set { } } = 4; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42), + // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // public static int P5 { get => 0; set; } = 5; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28), + // (10,33): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. + // public static int P7 { get; set { } } = 7; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P7").WithLocation(10, 33)); verifier.VerifyIL("C..cctor", """ { // Code size 56 (0x38) @@ -1594,7 +1612,13 @@ static void Main() verifier.VerifyDiagnostics( // (7,35): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. // public int P4 { get => field; set { } } = 4; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P4").WithLocation(7, 35)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P4").WithLocation(7, 35), + // (8,21): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // public int P5 { get => 0; set; } = 5; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 21), + // (10,26): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. + // public int P7 { get; set { } } = 7; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P7").WithLocation(10, 26)); verifier.VerifyIL("C..ctor", """ { // Code size 71 (0x47) @@ -1702,7 +1726,13 @@ static void Main() verifier.VerifyDiagnostics( // (7,35): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. // public int P4 { get => field; set { } } = 4; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P4").WithLocation(7, 35)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P4").WithLocation(7, 35), + // (8,21): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // public int P5 { get => 0; set; } = 5; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 21), + // (10,26): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. + // public int P7 { get; set { } } = 7; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P7").WithLocation(10, 26)); verifier.VerifyIL("C..ctor", """ { // Code size 65 (0x41) @@ -1810,18 +1840,25 @@ interface I // (8,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P5 { get => 0; set; } = 5; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P5").WithLocation(8, 16), + // (8,21): warning CS9265: The 'get' accessor of property 'I.P5' should use the backing 'field' because the other accessor is using it. + // public int P5 { get => 0; set; } = 5; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P5").WithLocation(8, 21), // (9,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P6 { get; set; } = 6; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P6").WithLocation(9, 16), // (10,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P7 { get; set { } } = 7; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P7").WithLocation(10, 16), + // (10,26): warning CS9265: The 'set' accessor of property 'I.P7' should use the backing 'field' because the other accessor is using it. + // public int P7 { get; set { } } = 7; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "I.P7").WithLocation(10, 26), // (11,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P8 { set { field = value; } } = 8; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P8").WithLocation(11, 16), // (12,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P9 { get { return field; } set { field = value; } } = 9; - Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P9").WithLocation(12, 16)); + Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P9").WithLocation(12, 16) + ); var containingType = comp.GetMember("I"); var actualFields = containingType.GetMembers().OfType().ToImmutableArray(); @@ -1934,8 +1971,14 @@ static void Main() expectedOutput: IncludeExpectedOutput("(0, 0, 3, 0, 0, 6, 0, 9)")); verifier.VerifyDiagnostics( // (7,42): warning CS9265: The 'set' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. - // public static int P4 { get => field; set { } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P4").WithLocation(7, 42)); + // static int P4 { get => field; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P4").WithLocation(7, 42), + // (8,28): warning CS9265: The 'get' accessor of property 'I.P5' should use the backing 'field' because the other accessor is using it. + // static int P5 { get => 0; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P5").WithLocation(8, 28), + // (10,33): warning CS9265: The 'set' accessor of property 'I.P7' should use the backing 'field' because the other accessor is using it. + // static int P7 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P7").WithLocation(10, 33)); var comp = (CSharpCompilation)verifier.Compilation; var containingType = comp.GetMember("I"); @@ -2006,9 +2049,15 @@ interface I // (7,16): error CS0525: Interfaces cannot contain instance fields // int P5 { get => 0; set; } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P5").WithLocation(7, 16), + // (7,21): warning CS9265: The 'get' accessor of property 'I.P5' should use the backing 'field' because the other accessor is using it. + // int P5 { get => 0; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P5").WithLocation(7, 21), // (9,16): error CS0525: Interfaces cannot contain instance fields // int P7 { get; set { } } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P7").WithLocation(9, 16), + // (9,26): warning CS9265: The 'set' accessor of property 'I.P7' should use the backing 'field' because the other accessor is using it. + // int P7 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "I.P7").WithLocation(9, 26), // (10,16): error CS0525: Interfaces cannot contain instance fields // int P8 { set { field = value; } } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P8").WithLocation(10, 16), @@ -2133,7 +2182,13 @@ static void Main() verifier.VerifyDiagnostics( // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. // public static int P4 { get => field; set { } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42), + // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // public static int P5 { get => 0; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28), + // (10,33): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. + // public static int P7 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P7").WithLocation(10, 33)); verifier.VerifyIL("C..cctor", """ { // Code size 56 (0x38) @@ -2256,7 +2311,13 @@ static void Main() verifier.VerifyDiagnostics( // (27,35): warning CS9265: The 'set' accessor of property 'C4.P4' should use the backing 'field' because the other accessor is using it. // public int P4 { get => field; set { } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C4.P4").WithLocation(27, 35)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C4.P4").WithLocation(27, 35), + // (34,21): warning CS9265: The 'get' accessor of property 'C5.P5' should use the backing 'field' because the other accessor is using it. + // public int P5 { get => default; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C5.P5").WithLocation(34, 21), + // (48,26): warning CS9265: The 'set' accessor of property 'C7.P7' should use the backing 'field' because the other accessor is using it. + // public int P7 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C7.P7").WithLocation(48, 26)); if (typeKind == "class") { verifier.VerifyIL("C1..ctor(int)", $$""" @@ -3575,6 +3636,9 @@ static B() // (6,50): warning CS9265: The 'set' accessor of property 'A.P5' should use the backing 'field' because the other accessor is using it. // public static int P5 { get => field; private set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "A.P5").WithLocation(6, 50), + // (7,41): warning CS9265: The 'set' accessor of property 'A.P7' should use the backing 'field' because the other accessor is using it. + // public static int P7 { get; private set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "A.P7").WithLocation(7, 41), // (13,9): error CS0272: The property or indexer 'A.P1' cannot be used in this context because the set accessor is inaccessible // P1 = 1; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "P1").WithArguments("A.P1").WithLocation(13, 9), @@ -3628,6 +3692,12 @@ public B() // (9,43): warning CS9265: The 'init' accessor of property 'A.P6' should use the backing 'field' because the other accessor is using it. // public int P6 { get => field; private init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "A.P6").WithLocation(9, 43), + // (10,34): warning CS9265: The 'set' accessor of property 'A.P7' should use the backing 'field' because the other accessor is using it. + // public int P7 { get; private set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "A.P7").WithLocation(10, 34), + // (11,34): warning CS9265: The 'init' accessor of property 'A.P8' should use the backing 'field' because the other accessor is using it. + // public int P8 { get; private init { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "A.P8").WithLocation(11, 34), // (17,9): error CS0272: The property or indexer 'A.P1' cannot be used in this context because the set accessor is inaccessible // P1 = 1; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "P1").WithArguments("A.P1").WithLocation(17, 9), @@ -4326,9 +4396,15 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use // (6,40): warning CS9265: The 'init' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. // object P4 { get => field; init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.P4").WithLocation(6, 40), + // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // object P6 { get => null; init; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(8, 26), // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. // object P8 { get => null; init { _ = field; } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), + // (12,31): warning CS9265: The 'init' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // object PA { get; init { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.PA").WithLocation(12, 31)); } else if (useReadOnlyType) { @@ -4342,12 +4418,18 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use // (8,21): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P6 { get => null; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P6").WithLocation(8, 21), + // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // object P6 { get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(8, 26), // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. // object P8 { get => null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), // (11,21): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P9 { get; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P9").WithLocation(11, 21), + // (12,31): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // object PA { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(12, 31), // (14,37): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) // object PC { get; set { field = value; } } Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(14, 37), @@ -4367,12 +4449,18 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use // (8,21): error CS8659: Auto-implemented property 'S.P6' cannot be marked 'readonly' because it has a 'set' accessor. // readonly object P6 { get => null; set; } Diagnostic(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, "P6").WithArguments("S.P6").WithLocation(8, 21), + // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // readonly object P6 { get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(8, 26), // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. // readonly object P8 { get => null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), // (11,21): error CS8659: Auto-implemented property 'S.P9' cannot be marked 'readonly' because it has a 'set' accessor. // readonly object P9 { get; set; } Diagnostic(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, "P9").WithArguments("S.P9").WithLocation(11, 21), + // (12,31): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // readonly object PA { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(12, 31), // (14,37): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) // readonly object PC { get; set { field = value; } } Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(14, 37), @@ -4386,9 +4474,15 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. // object P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(6, 40), + // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // object P6 { get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(8, 26), // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. // object P8 { get => null; set { _ = field; } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), + // (12,31): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // object PA { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(12, 31)); } var actualMembers = comp.GetMember("S").GetMembers().OfType().Select(f => $"{f.ToTestDisplayString()}: {f.IsReadOnly}"); var expectedMembers = new[] @@ -4444,12 +4538,18 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (5,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P6 { readonly get => null; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P6").WithLocation(5, 12), + // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // object P6 { readonly get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(5, 26), // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. // object P8 { readonly get => null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26), // (8,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P9 { readonly get; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P9").WithLocation(8, 12), + // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // object PA { readonly get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(9, 40), // (10,46): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) // object PC { readonly get; set { field = value; } } Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(10, 46)); @@ -4469,6 +4569,9 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (5,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P6").WithLocation(5, 12), + // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // object P6 { get => null; readonly set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(5, 26), // (5,48): error CS8658: Auto-implemented 'set' accessor 'S.P6.set' cannot be marked 'readonly'. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P6.set").WithLocation(5, 48), @@ -4481,6 +4584,9 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (8,40): error CS8658: Auto-implemented 'set' accessor 'S.P9.set' cannot be marked 'readonly'. // object P9 { get; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P9.set").WithLocation(8, 40), + // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // object PA { get; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(9, 40), // (10,46): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) // object PC { get; readonly set { field = value; } } Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(10, 46)); @@ -4494,9 +4600,15 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. // object P4 { readonly get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), + // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // object P6 { readonly get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(5, 26), // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. // object P8 { readonly get => null; set { _ = field; } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26), + // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // object PA { readonly get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(9, 40)); } else { @@ -4507,6 +4619,9 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. // object P4 { get => field; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), + // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // object P6 { get => null; readonly set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(5, 26), // (5,48): error CS8658: Auto-implemented 'set' accessor 'S.P6.set' cannot be marked 'readonly'. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P6.set").WithLocation(5, 48), @@ -4516,6 +4631,9 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (8,40): error CS8658: Auto-implemented 'set' accessor 'S.P9.set' cannot be marked 'readonly'. // object P9 { get; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P9.set").WithLocation(8, 40), + // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // object PA { get; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(9, 40), // (10,46): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) // object PC { get; readonly set { field = value; } } Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(10, 46)); @@ -4743,6 +4861,9 @@ struct S // (11,31): error CS8903: 'init' accessors cannot be marked 'readonly'. Mark 'S.Q4' readonly instead. // object Q4 { get; readonly init { } } Diagnostic(ErrorCode.ERR_InitCannotBeReadonly, "init").WithArguments("S.Q4").WithLocation(11, 31), + // (11,31): warning CS9265: The 'init' accessor of property 'S.Q4' should use the backing 'field' because the other accessor is using it. + // object Q4 { get; readonly init { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.Q4").WithLocation(11, 31), // (12,12): error CS8661: Cannot specify 'readonly' modifiers on both accessors of property or indexer 'S.Q5'. Instead, put a 'readonly' modifier on the property itself. // object Q5 { readonly get => field; readonly init { } } Diagnostic(ErrorCode.ERR_DuplicatePropertyReadOnlyMods, "Q5").WithArguments("S.Q5").WithLocation(12, 12), @@ -4783,6 +4904,9 @@ struct S // (9,12): error CS8664: 'S.Q2': 'readonly' can only be used on accessors if the property or indexer has both a get and a set accessor // object Q2 { readonly set { _ = field; } } Diagnostic(ErrorCode.ERR_ReadOnlyModMissingAccessor, "Q2").WithArguments("S.Q2").WithLocation(9, 12), + // (11,31): warning CS9265: The 'set' accessor of property 'S.Q4' should use the backing 'field' because the other accessor is using it. + // object Q4 { get; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.Q4").WithLocation(11, 31), // (12,12): error CS8661: Cannot specify 'readonly' modifiers on both accessors of property or indexer 'S.Q5'. Instead, put a 'readonly' modifier on the property itself. // object Q5 { readonly get => field; readonly set { } } Diagnostic(ErrorCode.ERR_DuplicatePropertyReadOnlyMods, "Q5").WithArguments("S.Q5").WithLocation(12, 12), @@ -4998,12 +5122,18 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (10,25): error CS8145: Auto-implemented properties cannot return by reference // ref object P8 { get => throw null; set; } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P8").WithLocation(10, 25), + // (10,30): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // ref object P8 { get => throw null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 30), // (10,49): error CS8147: Properties which return by reference cannot have set accessors // ref object P8 { get => throw null; set; } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "set").WithLocation(10, 49), // (11,25): error CS8145: Auto-implemented properties cannot return by reference // ref object P9 { get => throw null; init; } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P9").WithLocation(11, 25), + // (11,30): warning CS9265: The 'get' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // ref object P9 { get => throw null; init; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P9").WithLocation(11, 30), // (11,49): error CS8147: Properties which return by reference cannot have set accessors // ref object P9 { get => throw null; init; } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "init").WithLocation(11, 49), @@ -5040,12 +5170,18 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (16,25): error CS8145: Auto-implemented properties cannot return by reference // ref object PG { get; set { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PG").WithLocation(16, 25), + // (16,35): warning CS9265: The 'set' accessor of property 'S.PG' should use the backing 'field' because the other accessor is using it. + // ref object PG { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PG").WithLocation(16, 35), // (16,35): error CS8147: Properties which return by reference cannot have set accessors // ref object PG { get; set { } } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "set").WithLocation(16, 35), // (17,25): error CS8145: Auto-implemented properties cannot return by reference // ref object PH { get; init { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PH").WithLocation(17, 25), + // (17,35): warning CS9265: The 'init' accessor of property 'S.PH' should use the backing 'field' because the other accessor is using it. + // ref object PH { get; init { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.PH").WithLocation(17, 35), // (17,35): error CS8147: Properties which return by reference cannot have set accessors // ref object PH { get; init { } } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "init").WithLocation(17, 35), @@ -5110,6 +5246,9 @@ public void RefReturning_02(bool useStruct, bool useRefReadOnly) // (8,32): error CS8145: Auto-implemented properties cannot return by reference // static ref object P8 { get => throw null; set; } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P8").WithLocation(8, 32), + // (8,37): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // static ref object P8 { get => throw null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(8, 37), // (8,56): error CS8147: Properties which return by reference cannot have set accessors // static ref object P8 { get => throw null; set; } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "set").WithLocation(8, 56), @@ -5131,6 +5270,9 @@ public void RefReturning_02(bool useStruct, bool useRefReadOnly) // (11,32): error CS8145: Auto-implemented properties cannot return by reference // static ref object PG { get; set { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PG").WithLocation(11, 32), + // (11,42): warning CS9265: The 'set' accessor of property 'S.PG' should use the backing 'field' because the other accessor is using it. + // static ref object PG { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PG").WithLocation(11, 42), // (11,42): error CS8147: Properties which return by reference cannot have set accessors // static ref object PG { get; set { } } Diagnostic(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, "set").WithLocation(11, 42), @@ -7275,15 +7417,24 @@ class C // (3,25): error CS8051: Auto-implemented properties must have get accessors. // object P02 { set; } Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, setter).WithLocation(3, 25), + // (8,30): warning CS9265: The 'set' accessor of property 'C.P13' should use the backing 'field' because the other accessor is using it. + // object P13 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P13").WithLocation(8, 30), // (12,39): warning CS9265: The 'set' accessor of property 'C.P23' should use the backing 'field' because the other accessor is using it. // object P23 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P23").WithLocation(12, 39), + // (15,25): warning CS9265: The 'get' accessor of property 'C.P32' should use the backing 'field' because the other accessor is using it. + // object P32 { get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P32").WithLocation(15, 25), // (17,25): warning CS9265: The 'get' accessor of property 'C.P34' should use the backing 'field' because the other accessor is using it. // object P34 { get => null; set { field = value; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P34").WithLocation(17, 25), // (20,47): warning CS9265: The 'set' accessor of property 'C.P43' should use the backing 'field' because the other accessor is using it. // object P43 { get { return field; } set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P43").WithLocation(20, 47), + // (23,25): warning CS9265: The 'get' accessor of property 'C.P52' should use the backing 'field' because the other accessor is using it. + // object P52 { get { return null; } set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P52").WithLocation(23, 25), // (25,25): warning CS9265: The 'get' accessor of property 'C.P54' should use the backing 'field' because the other accessor is using it. // object P54 { get { return null; } set { field = value; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P54").WithLocation(25, 25)); @@ -8295,12 +8446,18 @@ partial interface I else { comp.VerifyEmitDiagnostics( - // (3,20): error CS0525: Interfaces cannot contain instance fields - // partial object P1 { get; set; } - Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(3, 20), - // (4,20): error CS0525: Interfaces cannot contain instance fields - // partial object P2 { get; init; } - Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P2").WithLocation(4, 20)); + // (3,20): error CS0525: Interfaces cannot contain instance fields + // partial object P1 { get; set; } + Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(3, 20), + // (3,30): warning CS9265: The 'set' accessor of property 'I.P1' should use the backing 'field' because the other accessor is using it. + // partial object P1 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P1").WithLocation(3, 30), + // (4,20): error CS0525: Interfaces cannot contain instance fields + // partial object P2 { get; init; } + Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P2").WithLocation(4, 20), + // (4,25): warning CS9265: The 'get' accessor of property 'I.P2' should use the backing 'field' because the other accessor is using it. + // partial object P2 { get => null; init; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P2").WithLocation(4, 25)); } var containingType = comp.GetMember("I"); @@ -8357,7 +8514,13 @@ partial interface I } else { - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (3,37): warning CS9265: The 'set' accessor of property 'I.P1' should use the backing 'field' because the other accessor is using it. + // static partial object P1 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P1").WithLocation(3, 37), + // (4,32): warning CS9265: The 'get' accessor of property 'I.P2' should use the backing 'field' because the other accessor is using it. + // static partial object P2 { get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P2").WithLocation(4, 32)); } var containingType = comp.GetMember("I"); @@ -8928,7 +9091,19 @@ static void Main() k__BackingField k__BackingField """)); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (8,44): warning CS9265: The 'set' accessor of property 'C.P6' should use the backing 'field' because the other accessor is using it. + // public static partial object P6 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P6").WithLocation(8, 44), + // (9,39): warning CS9265: The 'get' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. + // public static partial object P7 { get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P7").WithLocation(9, 39), + // (15,44): warning CS9265: The 'set' accessor of property 'C.Q6' should use the backing 'field' because the other accessor is using it. + // public static partial object Q6 { get; set { } } = 6; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.Q6").WithLocation(15, 44), + // (16,39): warning CS9265: The 'get' accessor of property 'C.Q7' should use the backing 'field' because the other accessor is using it. + // public static partial object Q7 { get => null; set; } = 7; + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Q7").WithLocation(16, 39)); var comp = (CSharpCompilation)verifier.Compilation; var containingType = comp.GetMember("C"); @@ -9303,6 +9478,15 @@ partial struct S { case (false, false): comp.VerifyEmitDiagnostics( + // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // partial object P5 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 39), + // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // partial object P6 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P6").WithLocation(8, 39), + // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use the backing 'field' because the other accessor is using it. + // partial object P7 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P7").WithLocation(9, 39), // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. // partial object P8 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), @@ -9327,9 +9511,18 @@ partial struct S // (7,29): error CS8663: Both partial member declarations must be readonly or neither may be readonly // readonly partial object P5 { get; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "P5").WithLocation(7, 29), + // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // readonly partial object P5 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 39), // (8,34): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P6 { readonly get; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "get").WithLocation(8, 34), + // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // partial object P6 { readonly get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P6").WithLocation(8, 39), + // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use the backing 'field' because the other accessor is using it. + // partial object P7 { get; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P7").WithLocation(9, 39), // (9,39): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P7 { get; readonly set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "set").WithLocation(9, 39), @@ -9369,9 +9562,18 @@ partial struct S // (7,29): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P5 { get; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "P5").WithLocation(7, 29), + // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // partial object P5 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 39), // (8,34): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P6 { get; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "get").WithLocation(8, 34), + // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // partial object P6 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P6").WithLocation(8, 39), + // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use the backing 'field' because the other accessor is using it. + // partial object P7 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P7").WithLocation(9, 39), // (9,39): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P7 { get; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "set").WithLocation(9, 39), @@ -9396,6 +9598,15 @@ partial struct S // (6,20): error CS8664: 'S.P4': 'readonly' can only be used on accessors if the property or indexer has both a get and a set accessor // partial object P4 { readonly set; } Diagnostic(ErrorCode.ERR_ReadOnlyModMissingAccessor, "P4").WithArguments("S.P4").WithLocation(6, 20), + // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // readonly partial object P5 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 39), + // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // partial object P6 { readonly get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P6").WithLocation(8, 39), + // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use the backing 'field' because the other accessor is using it. + // partial object P7 { get; readonly set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P7").WithLocation(9, 39), // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. // partial object P8 { readonly get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), @@ -9538,16 +9749,22 @@ partial class B targetFramework: GetTargetFramework(useInit)); comp.VerifyEmitDiagnostics( // (3,35): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type - // partial object P1 { [A(field)] get { return field; } } + // partial object P1 { [A(field)] get { return field; } } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(3, 35), + // (4,32): warning CS9265: The 'get' accessor of property 'B.P2' should use the backing 'field' because the other accessor is using it. + // partial object P2 { get { return null; } [A(field)] init; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P2").WithLocation(4, 32), // (4,56): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type - // partial object P2 { get { return null; } [A(field)] set; } + // partial object P2 { get { return null; } [A(field)] init; } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(4, 56), // (5,35): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type - // partial object P3 { [A(field)] get; } + // partial object P3 { [A(field)] get; } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(5, 35), + // (6,32): warning CS9265: The 'get' accessor of property 'B.P4' should use the backing 'field' because the other accessor is using it. + // partial object P4 { get { return null; } init; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P4").WithLocation(6, 32), // (6,40): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type - // partial object P4 { get; [A(field)] set; } + // partial object P4 { get; [A(field)] init; } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(6, 40)); var containingType = comp.GetMember("B"); @@ -9611,12 +9828,18 @@ partial class B // (4,50): warning CS9265: The 'set' accessor of property 'B.P2' should use the backing 'field' because the other accessor is using it. // partial object P2 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.P2").WithLocation(4, 50), + // (5,36): warning CS9265: The 'get' accessor of property 'B.P3' should use the backing 'field' because the other accessor is using it. + // partial object P3 { get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P3").WithLocation(5, 36), // (6,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored. // [field: A] partial object Q1 { get => null; set { } } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(6, 6), // (7,50): warning CS9265: The 'set' accessor of property 'B.Q2' should use the backing 'field' because the other accessor is using it. // [field: A] partial object Q2 { get => field; set { } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.Q2").WithLocation(7, 50)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.Q2").WithLocation(7, 50), + // (8,36): warning CS9265: The 'get' accessor of property 'B.Q3' should use the backing 'field' because the other accessor is using it. + // [field: A] partial object Q3 { get => null; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.Q3").WithLocation(8, 36)); var containingType = comp.GetMember("B"); var actualFields = containingType.GetMembers().OfType().ToImmutableArray(); diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs index 252bf355fe09b..db8b84f835efb 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs @@ -3382,7 +3382,10 @@ class Test1 : I1 Diagnostic(ErrorCode.ERR_FeatureInPreview, "P1").WithArguments("field keyword").WithLocation(4, 24)); break; case (true, false): - compilation1.VerifyDiagnostics(); + compilation1.VerifyDiagnostics( + // (6,9): warning CS9265: The 'get' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // get + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I1.P1").WithLocation(6, 9)); break; case (false, true): compilation1.VerifyDiagnostics( @@ -3399,7 +3402,10 @@ class Test1 : I1 compilation1.VerifyDiagnostics( // (4,9): error CS0525: Interfaces cannot contain instance fields // int P1 - Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9)); + Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9), + // (6,9): warning CS9265: The 'get' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // get + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I1.P1").WithLocation(6, 9)); break; } @@ -3465,7 +3471,10 @@ class Test1 : I1 } else { - compilation1.VerifyDiagnostics(); + compilation1.VerifyDiagnostics( + // (6,9): warning CS9265: The 'get' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // get + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I1.P1").WithLocation(6, 9)); } var p1 = compilation1.GetMember("I1.P1"); @@ -3528,7 +3537,10 @@ class Test1 : I1 Diagnostic(ErrorCode.ERR_FeatureInPreview, "P1").WithArguments("field keyword").WithLocation(4, 24)); break; case (true, false): - compilation1.VerifyDiagnostics(); + compilation1.VerifyDiagnostics( + // (7,9): warning CS9265: The 'set' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // set => System.Console.WriteLine("set P1"); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I1.P1").WithLocation(7, 9)); break; case (false, true): compilation1.VerifyDiagnostics( @@ -3545,7 +3557,10 @@ class Test1 : I1 compilation1.VerifyDiagnostics( // (4,9): error CS0525: Interfaces cannot contain instance fields // int P1 - Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9)); + Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9), + // (7,9): warning CS9265: The 'set' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // set => System.Console.WriteLine("set P1"); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I1.P1").WithLocation(7, 9)); break; } @@ -3607,7 +3622,10 @@ class Test1 : I1 } else { - compilation1.VerifyDiagnostics(); + compilation1.VerifyDiagnostics( + // (7,9): warning CS9265: The 'set' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // set => System.Console.WriteLine("set P1"); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I1.P1").WithLocation(7, 9)); } var p1 = compilation1.GetMember("I1.P1"); diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/PartialPropertiesTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/PartialPropertiesTests.cs index b20d76e5f052d..d73848ca97db2 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/PartialPropertiesTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/PartialPropertiesTests.cs @@ -1521,6 +1521,9 @@ partial class C // (11,17): error CS8799: Both partial member declarations must have identical accessibility modifiers. // partial int P1 { private get => 1; private set; } Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "P1").WithLocation(11, 17), + // (11,30): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // partial int P1 { private get => 1; private set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(11, 30), // (11,30): error CS8799: Both partial member declarations must have identical accessibility modifiers. // partial int P1 { private get => 1; private set; } Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "get").WithLocation(11, 30), @@ -5033,7 +5036,13 @@ partial class C """; var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (4,32): warning CS9265: The 'get' accessor of property 'C.Prop1' should use the backing 'field' because the other accessor is using it. + // public partial int Prop1 { get => 1; set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Prop1").WithLocation(4, 32), + // (7,37): warning CS9265: The 'set' accessor of property 'C.Prop2' should use the backing 'field' because the other accessor is using it. + // public partial int Prop2 { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.Prop2").WithLocation(7, 37)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/74679")] diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 9c3566875c603..b406f9a201083 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -8141,9 +8141,15 @@ public void CS0501ERR_ConcreteMissingBody02() Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("C.R.get").WithLocation(5, 30)); CreateCompilation(text).VerifyDiagnostics( - // (5,30): warning CS0626: Method, operator, or accessor 'C.R.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // public extern object R { get; } // no error - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("C.R.get").WithLocation(5, 30)); + // (3,25): warning CS9265: The 'set' accessor of property 'C.P' should use the backing 'field' because the other accessor is using it. + // public int P { get; set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P").WithLocation(3, 25), + // (4,20): warning CS9265: The 'get' accessor of property 'C.Q' should use the backing 'field' because the other accessor is using it. + // public int Q { get { return 0; } set; } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Q").WithLocation(4, 20), + // (5,30): warning CS0626: Method, operator, or accessor 'C.R.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // public extern object R { get; } // no error + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("C.R.get").WithLocation(5, 30)); } [Fact] From 7c0f6c18292c1a6c3ab907466609c2924f1579d6 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 8 Oct 2024 16:16:51 -0700 Subject: [PATCH 3/7] special handling for initializers --- .../CSharp/Portable/CSharpResources.resx | 2 +- .../Symbols/Source/SourcePropertySymbol.cs | 31 +--- .../Source/SourcePropertySymbolBase.cs | 65 ++++++-- ...nthesizedRecordEqualityContractProperty.cs | 3 +- .../SynthesizedRecordPropertySymbol.cs | 3 +- .../Portable/xlf/CSharpResources.cs.xlf | 4 +- .../Portable/xlf/CSharpResources.de.xlf | 4 +- .../Portable/xlf/CSharpResources.es.xlf | 4 +- .../Portable/xlf/CSharpResources.fr.xlf | 4 +- .../Portable/xlf/CSharpResources.it.xlf | 4 +- .../Portable/xlf/CSharpResources.ja.xlf | 4 +- .../Portable/xlf/CSharpResources.ko.xlf | 4 +- .../Portable/xlf/CSharpResources.pl.xlf | 4 +- .../Portable/xlf/CSharpResources.pt-BR.xlf | 4 +- .../Portable/xlf/CSharpResources.ru.xlf | 4 +- .../Portable/xlf/CSharpResources.tr.xlf | 4 +- .../Portable/xlf/CSharpResources.zh-Hans.xlf | 4 +- .../Portable/xlf/CSharpResources.zh-Hant.xlf | 4 +- .../CSharp/Test/Emit3/FieldKeywordTests.cs | 144 +++++++++++++++++- 19 files changed, 227 insertions(+), 73 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 701591d6cb7ac..db2652235200e 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -8003,7 +8003,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Non-nullable property must contain a non-null value when exiting constructor. Consider adding the 'required' modifier, or declaring the property as nullable, or adding '[field: MaybeNull, AllowNull]' attributes. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. Property accessor should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index ca3cf9e382356..9b8e2ac4698fc 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -74,7 +74,7 @@ private static SourcePropertySymbol Create( string? aliasQualifierOpt; string memberName = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(binder, explicitInterfaceSpecifier, name, diagnostics, out explicitInterfaceType, out aliasQualifierOpt); - var symbol = new SourcePropertySymbol( + return new SourcePropertySymbol( containingType, syntax, hasGetAccessor: getSyntax != null || isExpressionBodied, @@ -88,30 +88,11 @@ private static SourcePropertySymbol Create( hasAutoPropertySet: hasAutoPropertySet, isExpressionBodied: isExpressionBodied, accessorsHaveImplementation: accessorsHaveImplementation, - usesFieldKeyword: getterUsesFieldKeyword || setterUsesFieldKeyword, + getterUsesFieldKeyword: getterUsesFieldKeyword, + setterUsesFieldKeyword: setterUsesFieldKeyword, memberName, location, diagnostics); - - if (binder.Compilation.IsFeatureEnabled(MessageID.IDS_FeatureFieldKeyword)) - { - AccessorDeclarationSyntax? accessorToBlame = null; - if (hasSetAccessorImplementation && !setterUsesFieldKeyword && (hasAutoPropertyGet || getterUsesFieldKeyword)) - { - accessorToBlame = setSyntax; - } - else if (hasGetAccessorImplementation && !getterUsesFieldKeyword && (hasAutoPropertySet || setterUsesFieldKeyword)) - { - accessorToBlame = getSyntax; - } - - if (accessorToBlame is not null) - { - diagnostics.Add(ErrorCode.WRN_AccessorDoesNotUseBackingField, accessorToBlame.Keyword, [accessorToBlame.Keyword.ValueText, symbol]); - } - } - - return symbol; } private SourcePropertySymbol( @@ -128,7 +109,8 @@ private SourcePropertySymbol( bool hasAutoPropertySet, bool isExpressionBodied, bool accessorsHaveImplementation, - bool usesFieldKeyword, + bool getterUsesFieldKeyword, + bool setterUsesFieldKeyword, string memberName, Location location, BindingDiagnosticBag diagnostics) @@ -147,7 +129,8 @@ private SourcePropertySymbol( hasAutoPropertySet: hasAutoPropertySet, isExpressionBodied: isExpressionBodied, accessorsHaveImplementation: accessorsHaveImplementation, - usesFieldKeyword: usesFieldKeyword, + getterUsesFieldKeyword: getterUsesFieldKeyword, + setterUsesFieldKeyword: setterUsesFieldKeyword, syntax.Type.SkipScoped(out _).GetRefKindInLocalOrReturn(diagnostics), memberName, syntax.AttributeLists, diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs index aca35156e28ea..dca69c44eb91a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs @@ -31,12 +31,13 @@ private enum Flags : ushort IsExpressionBodied = 1 << 0, HasAutoPropertyGet = 1 << 1, HasAutoPropertySet = 1 << 2, - UsesFieldKeyword = 1 << 3, - IsExplicitInterfaceImplementation = 1 << 4, - HasInitializer = 1 << 5, - AccessorsHaveImplementation = 1 << 6, - HasExplicitAccessModifier = 1 << 7, - RequiresBackingField = 1 << 8, + GetterUsesFieldKeyword = 1 << 4, + SetterUsesFieldKeyword = 1 << 5, + IsExplicitInterfaceImplementation = 1 << 6, + HasInitializer = 1 << 7, + AccessorsHaveImplementation = 1 << 8, + HasExplicitAccessModifier = 1 << 9, + RequiresBackingField = 1 << 10, } // TODO (tomat): consider splitting into multiple subclasses/rare data. @@ -90,7 +91,8 @@ protected SourcePropertySymbolBase( bool hasAutoPropertySet, bool isExpressionBodied, bool accessorsHaveImplementation, - bool usesFieldKeyword, + bool getterUsesFieldKeyword, + bool setterUsesFieldKeyword, RefKind refKind, string memberName, SyntaxList indexerNameAttributeLists, @@ -133,9 +135,14 @@ protected SourcePropertySymbolBase( _propertyFlags |= Flags.HasAutoPropertySet; } - if (usesFieldKeyword) + if (getterUsesFieldKeyword) { - _propertyFlags |= Flags.UsesFieldKeyword; + _propertyFlags |= Flags.GetterUsesFieldKeyword; + } + + if (setterUsesFieldKeyword) + { + _propertyFlags |= Flags.SetterUsesFieldKeyword; } if (hasInitializer) @@ -171,7 +178,7 @@ protected SourcePropertySymbolBase( _name = _lazySourceName = memberName; } - if (usesFieldKeyword || hasAutoPropertyGet || hasAutoPropertySet || hasInitializer) + if (getterUsesFieldKeyword || setterUsesFieldKeyword || hasAutoPropertyGet || hasAutoPropertySet || hasInitializer) { Debug.Assert(!IsIndexer); _propertyFlags |= Flags.RequiresBackingField; @@ -305,6 +312,39 @@ protected void CheckInitializerIfNeeded(BindingDiagnosticBag diagnostics) } } +#nullable enable + private void CheckFieldKeywordUsage(BindingDiagnosticBag diagnostics) + { + if (!this.DeclaringCompilation.IsFeatureEnabled(MessageID.IDS_FeatureFieldKeyword)) + { + return; + } + + check((SourcePropertySymbolBase?)PartialImplementationPart ?? this, diagnostics); + + static void check(SourcePropertySymbolBase @this, BindingDiagnosticBag diagnostics) + { + SourcePropertyAccessorSymbol? accessorToBlame = null; + var propertyFlags = @this._propertyFlags; + var getterUsesFieldKeyword = (propertyFlags & Flags.GetterUsesFieldKeyword) != 0; + var setterUsesFieldKeyword = (propertyFlags & Flags.SetterUsesFieldKeyword) != 0; + if (@this._setMethod is { IsAutoPropertyAccessor: false } setMethod && !setterUsesFieldKeyword && !@this.IsSetOnEitherPart(Flags.HasInitializer) && (@this.HasAutoPropertyGet || getterUsesFieldKeyword)) + { + accessorToBlame = setMethod; + } + else if (@this._getMethod is { IsAutoPropertyAccessor: false } getMethod && !getterUsesFieldKeyword && (@this.HasAutoPropertySet || setterUsesFieldKeyword)) + { + accessorToBlame = getMethod; + } + + if (accessorToBlame is not null) + { + diagnostics.Add(ErrorCode.WRN_AccessorDoesNotUseBackingField, accessorToBlame.GetFirstLocation(), accessorToBlame); + } + } + } +#nullable disable + public sealed override RefKind RefKind { get @@ -648,10 +688,10 @@ public bool HasSkipLocalsInitAttribute } internal bool IsAutoPropertyOrUsesFieldKeyword - => IsSetOnEitherPart(Flags.HasAutoPropertyGet | Flags.HasAutoPropertySet | Flags.UsesFieldKeyword); + => IsSetOnEitherPart(Flags.HasAutoPropertyGet | Flags.HasAutoPropertySet | Flags.GetterUsesFieldKeyword | Flags.SetterUsesFieldKeyword); internal bool UsesFieldKeyword - => IsSetOnEitherPart(Flags.UsesFieldKeyword); + => IsSetOnEitherPart(Flags.GetterUsesFieldKeyword | Flags.SetterUsesFieldKeyword); protected bool HasExplicitAccessModifier => (_propertyFlags & Flags.HasExplicitAccessModifier) != 0; @@ -811,6 +851,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, this.CheckModifiers(isExplicitInterfaceImplementation, Location, IsIndexer, diagnostics); CheckInitializerIfNeeded(diagnostics); + CheckFieldKeywordUsage(diagnostics); if (RefKind != RefKind.None && IsRequired) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEqualityContractProperty.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEqualityContractProperty.cs index 25d605aae2452..260dc11f240ce 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEqualityContractProperty.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEqualityContractProperty.cs @@ -36,7 +36,8 @@ public SynthesizedRecordEqualityContractProperty(SourceMemberContainerTypeSymbol hasAutoPropertySet: false, isExpressionBodied: false, accessorsHaveImplementation: true, - usesFieldKeyword: false, + getterUsesFieldKeyword: false, + setterUsesFieldKeyword: false, RefKind.None, PropertyName, indexerNameAttributeLists: new SyntaxList(), diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordPropertySymbol.cs index 898b4c160e30a..45a0afecdc918 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordPropertySymbol.cs @@ -34,7 +34,8 @@ public SynthesizedRecordPropertySymbol( hasAutoPropertySet: true, isExpressionBodied: false, accessorsHaveImplementation: true, - usesFieldKeyword: false, + getterUsesFieldKeyword: false, + setterUsesFieldKeyword: false, RefKind.None, backingParameter.Name, indexerNameAttributeLists: new SyntaxList(), diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 63635c8778d73..dce2328321635 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 0080e753709f5..c84002f6aa8dc 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 5e7835b49081f..b213345d4cdd2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index aebaf7c2fab9e..9f56612a7f1be 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 61ca3a049bf03..64de7fd1f656b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 36d3fe0726386..eff970d3cdf09 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index e86e5fe14d7c3..9ad3274d4a32a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index b4f7631a5b43b..3b79e19eba6ea 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index a39a9b1a2dff2..240bae333f5d7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index ece7b0a0962e8..e158647cadc73 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 31c803c03529f..ad5c23143262e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 653d52550bf54..a5c1209ffb29a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index d0ef09b50e80c..48ea76eb28f10 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2663,8 +2663,8 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. + '{0}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs index 31a68ae315f49..0ee88d6819292 100644 --- a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs @@ -215,12 +215,12 @@ object P4 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: 'C.P1.get' should use the backing 'field' because the other accessor is using it. // get { return _field; } // 1 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(6, 9), - // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P1.get").WithLocation(6, 9), + // (13,9): warning CS9265: 'C.P2.set' should use the backing 'field' because the other accessor is using it. // set { _field = value; } // 2 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(13, 9)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("C.P2.set").WithLocation(13, 9)); } [Fact] @@ -245,12 +245,140 @@ object P2 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: 'C.P1.get' should use the backing 'field' because the other accessor is using it. // get { return _field; } // 1 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(6, 9), - // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P1.get").WithLocation(6, 9), + // (13,9): warning CS9265: 'C.P2.set' should use the backing 'field' because the other accessor is using it. // set { _field = value; } // 2 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(13, 9)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("C.P2.set").WithLocation(13, 9)); + } + + [Fact] + public void MigratingToFieldKeyword_03() + { + string source = """ + partial class C + { + object _field; + partial object P1 { get; set; } + partial object P1 + { + get { return _field; } // 1 + set; + } + + partial object P2 { get; set; } + partial object P2 + { + get; + set { _field = value; } // 2 + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (7,9): warning CS9265: 'C.P1.get' should use the backing 'field' because the other accessor is using it. + // get { return _field; } // 1 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P1.get").WithLocation(7, 9), + // (15,9): warning CS9265: 'C.P2.set' should use the backing 'field' because the other accessor is using it. + // set { _field = value; } // 2 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("C.P2.set").WithLocation(15, 9)); + } + + [Fact] + public void PleaseWork_01() + { + var source = """ + partial class C + { + partial string Prop { get; set; } = "1"; + partial string Prop { get => field; set => field = value; } = "2"; + } + """; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics(); + } + + [Fact] + public void MigratingToFieldKeyword_04() + { + string source = """ + partial class C + { + object _field; + + partial object P1 { get; set; } + partial object P1 + { + get { return _field; } // 1 + set; + } = "1"; + + partial object P2 { get; set; } + partial object P2 + { + get; + set { _field = value; } // ok: backing field is still being assigned + } = "2"; + + partial object P3 { get; set; } = "3"; + partial object P3 + { + get { return _field; } // 2 + set; + } + + partial object P4 { get; set; } = "4"; + partial object P4 + { + get; + set { _field = value; } // ok: backing field is still being assigned + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (8,9): warning CS9265: 'C.P1.get' should use the backing 'field' because the other accessor is using it. + // get { return _field; } // 1 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P1.get").WithLocation(8, 9), + // (22,9): warning CS9265: 'C.P3.get' should use the backing 'field' because the other accessor is using it. + // get { return _field; } // 2 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P3.get").WithLocation(22, 9)); + } + + [Fact] + public void MigratingToFieldKeyword_05() + { + // Do not warn for a setter not using the 'field' when an initializer is present. + string source = """ + interface I + { + public string Prop { get; set; } + } + + class ReadonlyC1 : I + { + public string Prop { get; set => throw null!; } // 1 + } + + class ReadonlyC2 : I + { + public string Prop { get; set => throw null!; } = null!; // ok: field is being assigned + } + + class ReadonlyC3 : I + { + public string Prop { get => throw null!; set; } = null!; // 2 + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (8,31): warning CS9265: 'ReadonlyC1.Prop.set' should use the backing 'field' because the other accessor is using it. + // public string Prop { get; set => throw null!; } // 1 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("ReadonlyC1.Prop.set").WithLocation(8, 31), + // (18,26): warning CS9265: 'ReadonlyC3.Prop.get' should use the backing 'field' because the other accessor is using it. + // public string Prop { get => throw null!; set; } = null!; // 2 + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("ReadonlyC3.Prop.get").WithLocation(18, 26)); } [Fact] From b6903fd284662b343199ed5a5b43af50dab5b4e3 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 9 Oct 2024 09:54:35 -0700 Subject: [PATCH 4/7] test churn --- .../CSharp/Portable/CSharpResources.resx | 2 +- .../Source/SourcePropertySymbolBase.cs | 10 +- .../Portable/xlf/CSharpResources.cs.xlf | 4 +- .../Portable/xlf/CSharpResources.de.xlf | 4 +- .../Portable/xlf/CSharpResources.es.xlf | 4 +- .../Portable/xlf/CSharpResources.fr.xlf | 4 +- .../Portable/xlf/CSharpResources.it.xlf | 4 +- .../Portable/xlf/CSharpResources.ja.xlf | 4 +- .../Portable/xlf/CSharpResources.ko.xlf | 4 +- .../Portable/xlf/CSharpResources.pl.xlf | 4 +- .../Portable/xlf/CSharpResources.pt-BR.xlf | 4 +- .../Portable/xlf/CSharpResources.ru.xlf | 4 +- .../Portable/xlf/CSharpResources.tr.xlf | 4 +- .../Portable/xlf/CSharpResources.zh-Hans.xlf | 4 +- .../Portable/xlf/CSharpResources.zh-Hant.xlf | 4 +- .../CSharp/Test/Emit3/FieldKeywordTests.cs | 122 +++++------------- 16 files changed, 69 insertions(+), 117 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index db2652235200e..701591d6cb7ac 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -8003,7 +8003,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Non-nullable property must contain a non-null value when exiting constructor. Consider adding the 'required' modifier, or declaring the property as nullable, or adding '[field: MaybeNull, AllowNull]' attributes. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. Property accessor should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs index dca69c44eb91a..b44dbc902298f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs @@ -339,7 +339,15 @@ static void check(SourcePropertySymbolBase @this, BindingDiagnosticBag diagnosti if (accessorToBlame is not null) { - diagnostics.Add(ErrorCode.WRN_AccessorDoesNotUseBackingField, accessorToBlame.GetFirstLocation(), accessorToBlame); + var accessorName = accessorToBlame switch + { + { MethodKind: MethodKind.PropertyGet, IsInitOnly: false } => SyntaxFacts.GetText(SyntaxKind.GetKeyword), + { MethodKind: MethodKind.PropertySet, IsInitOnly: false } => SyntaxFacts.GetText(SyntaxKind.SetKeyword), + { MethodKind: MethodKind.PropertySet, IsInitOnly: true } => SyntaxFacts.GetText(SyntaxKind.InitKeyword), + _ => throw ExceptionUtilities.UnexpectedValue(accessorToBlame) + }; + + diagnostics.Add(ErrorCode.WRN_AccessorDoesNotUseBackingField, accessorToBlame.GetFirstLocation(), accessorName, @this); } } } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index dce2328321635..63635c8778d73 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index c84002f6aa8dc..0080e753709f5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index b213345d4cdd2..5e7835b49081f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 9f56612a7f1be..aebaf7c2fab9e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 64de7fd1f656b..61ca3a049bf03 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index eff970d3cdf09..36d3fe0726386 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 9ad3274d4a32a..e86e5fe14d7c3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 3b79e19eba6ea..b4f7631a5b43b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 240bae333f5d7..a39a9b1a2dff2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index e158647cadc73..ece7b0a0962e8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index ad5c23143262e..31c803c03529f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index a5c1209ffb29a..653d52550bf54 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 48ea76eb28f10..d0ef09b50e80c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2663,8 +2663,8 @@ - '{0}' should use the backing 'field' because the other accessor is using it. - '{0}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs index 0ee88d6819292..e33457b162435 100644 --- a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs @@ -193,19 +193,19 @@ object P1 get { return _field; } // 1 set { field = value; } } - + object P2 { get { return field; } set { _field = value; } // 2 } - + object P3 { get { return _field; } set { _field = value; } } - + object P4 { get { return field; } @@ -215,12 +215,12 @@ object P4 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,9): warning CS9265: 'C.P1.get' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. // get { return _field; } // 1 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P1.get").WithLocation(6, 9), - // (13,9): warning CS9265: 'C.P2.set' should use the backing 'field' because the other accessor is using it. + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(6, 9), + // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. // set { _field = value; } // 2 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("C.P2.set").WithLocation(13, 9)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(13, 9)); } [Fact] @@ -235,7 +235,7 @@ object P1 get { return _field; } // 1 set; } - + object P2 { get; @@ -245,12 +245,12 @@ object P2 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,9): warning CS9265: 'C.P1.get' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. // get { return _field; } // 1 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P1.get").WithLocation(6, 9), - // (13,9): warning CS9265: 'C.P2.set' should use the backing 'field' because the other accessor is using it. + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(6, 9), + // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. // set { _field = value; } // 2 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("C.P2.set").WithLocation(13, 9)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(13, 9)); } [Fact] @@ -266,7 +266,7 @@ partial object P1 get { return _field; } // 1 set; } - + partial object P2 { get; set; } partial object P2 { @@ -277,26 +277,12 @@ partial object P2 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (7,9): warning CS9265: 'C.P1.get' should use the backing 'field' because the other accessor is using it. + // (7,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. // get { return _field; } // 1 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P1.get").WithLocation(7, 9), - // (15,9): warning CS9265: 'C.P2.set' should use the backing 'field' because the other accessor is using it. + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(7, 9), + // (15,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. // set { _field = value; } // 2 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("C.P2.set").WithLocation(15, 9)); - } - - [Fact] - public void PleaseWork_01() - { - var source = """ - partial class C - { - partial string Prop { get; set; } = "1"; - partial string Prop { get => field; set => field = value; } = "2"; - } - """; - var comp = CreateCompilation(source); - comp.VerifyDiagnostics(); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(15, 9)); } [Fact] @@ -313,7 +299,7 @@ partial object P1 get { return _field; } // 1 set; } = "1"; - + partial object P2 { get; set; } partial object P2 { @@ -327,7 +313,7 @@ partial object P3 get { return _field; } // 2 set; } - + partial object P4 { get; set; } = "4"; partial object P4 { @@ -338,12 +324,12 @@ partial object P4 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (8,9): warning CS9265: 'C.P1.get' should use the backing 'field' because the other accessor is using it. + // (8,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. // get { return _field; } // 1 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P1.get").WithLocation(8, 9), - // (22,9): warning CS9265: 'C.P3.get' should use the backing 'field' because the other accessor is using it. + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(8, 9), + // (22,9): warning CS9265: The 'get' accessor of property 'C.P3' should use the backing 'field' because the other accessor is using it. // get { return _field; } // 2 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("C.P3.get").WithLocation(22, 9)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P3").WithLocation(22, 9)); } [Fact] @@ -360,12 +346,12 @@ class ReadonlyC1 : I { public string Prop { get; set => throw null!; } // 1 } - + class ReadonlyC2 : I { public string Prop { get; set => throw null!; } = null!; // ok: field is being assigned } - + class ReadonlyC3 : I { public string Prop { get => throw null!; set; } = null!; // 2 @@ -373,12 +359,12 @@ class ReadonlyC3 : I """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (8,31): warning CS9265: 'ReadonlyC1.Prop.set' should use the backing 'field' because the other accessor is using it. + // (8,31): warning CS9265: The 'set' accessor of property 'ReadonlyC1.Prop' should use the backing 'field' because the other accessor is using it. // public string Prop { get; set => throw null!; } // 1 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("ReadonlyC1.Prop.set").WithLocation(8, 31), - // (18,26): warning CS9265: 'ReadonlyC3.Prop.get' should use the backing 'field' because the other accessor is using it. + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "ReadonlyC1.Prop").WithLocation(8, 31), + // (18,26): warning CS9265: The 'get' accessor of property 'ReadonlyC3.Prop' should use the backing 'field' because the other accessor is using it. // public string Prop { get => throw null!; set; } = null!; // 2 - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("ReadonlyC3.Prop.get").WithLocation(18, 26)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "ReadonlyC3.Prop").WithLocation(18, 26)); } [Fact] @@ -1570,15 +1556,9 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(1, 2, 3, 4, 0, 6, 7, 9)")); verifier.VerifyDiagnostics( - // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. - // public static int P4 { get => field; set { } } = 4; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42), // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. // public static int P5 { get => 0; set; } = 5; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28), - // (10,33): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. - // public static int P7 { get; set { } } = 7; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P7").WithLocation(10, 33)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28)); verifier.VerifyIL("C..cctor", """ { // Code size 56 (0x38) @@ -1668,15 +1648,9 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(1, 2, 3, 4, 0, 6, 7, 9)")); verifier.VerifyDiagnostics( - // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. - // public static int P4 { get => field; set { } } = 4; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42), // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. // public static int P5 { get => 0; set; } = 5; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28), - // (10,33): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. - // public static int P7 { get; set { } } = 7; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P7").WithLocation(10, 33)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28)); verifier.VerifyIL("C..cctor", """ { // Code size 56 (0x38) @@ -1738,15 +1712,9 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(useInit, "(1, 2, 3, 4, 0, 6, 7, 9)")); verifier.VerifyDiagnostics( - // (7,35): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. - // public int P4 { get => field; set { } } = 4; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P4").WithLocation(7, 35), // (8,21): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. // public int P5 { get => 0; set; } = 5; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 21), - // (10,26): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. - // public int P7 { get; set { } } = 7; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P7").WithLocation(10, 26)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 21)); verifier.VerifyIL("C..ctor", """ { // Code size 71 (0x47) @@ -1852,15 +1820,9 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(useInit, "(1, 2, 3, 4, 0, 6, 7, 9)")); verifier.VerifyDiagnostics( - // (7,35): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. - // public int P4 { get => field; set { } } = 4; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P4").WithLocation(7, 35), // (8,21): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. // public int P5 { get => 0; set; } = 5; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 21), - // (10,26): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. - // public int P7 { get; set { } } = 7; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P7").WithLocation(10, 26)); + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 21)); verifier.VerifyIL("C..ctor", """ { // Code size 65 (0x41) @@ -1962,9 +1924,6 @@ interface I // (7,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P4 { get => field; set { } } = 4; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P4").WithLocation(7, 16), - // (7,35): warning CS9265: The 'set' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. - // public int P4 { get => field; set { } } = 4; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "I.P4").WithLocation(7, 35), // (8,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P5 { get => 0; set; } = 5; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P5").WithLocation(8, 16), @@ -1977,9 +1936,6 @@ interface I // (10,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P7 { get; set { } } = 7; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P7").WithLocation(10, 16), - // (10,26): warning CS9265: The 'set' accessor of property 'I.P7' should use the backing 'field' because the other accessor is using it. - // public int P7 { get; set { } } = 7; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "I.P7").WithLocation(10, 26), // (11,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P8 { set { field = value; } } = 8; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P8").WithLocation(11, 16), @@ -8832,9 +8788,6 @@ partial interface I if (useStatic) { comp.VerifyEmitDiagnostics( - // (5,46): warning CS9265: The 'set' accessor of property 'I.P3' should use the backing 'field' because the other accessor is using it. - // static partial object P3 { get => field; set { } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P3").WithLocation(5, 46), // (6,32): warning CS9265: The 'get' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. // static partial object P4 { get => null; set { field = value; } } = 4; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P4").WithLocation(6, 32)); @@ -8851,9 +8804,6 @@ partial interface I // (5,27): error CS8053: Instance properties in interfaces cannot have initializers. // partial object P3 { get; set; } = 3; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P3").WithLocation(5, 27), - // (5,46): warning CS9265: The 'set' accessor of property 'I.P3' should use the backing 'field' because the other accessor is using it. - // partial object P3 { get => field; set { } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P3").WithLocation(5, 46), // (6,27): error CS8053: Instance properties in interfaces cannot have initializers. // partial object P4 { get => null; set { field = value; } } = 4; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P4").WithLocation(6, 27), @@ -9220,15 +9170,9 @@ static void Main() k__BackingField """)); verifier.VerifyDiagnostics( - // (8,44): warning CS9265: The 'set' accessor of property 'C.P6' should use the backing 'field' because the other accessor is using it. - // public static partial object P6 { get; set { } } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P6").WithLocation(8, 44), // (9,39): warning CS9265: The 'get' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. // public static partial object P7 { get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P7").WithLocation(9, 39), - // (15,44): warning CS9265: The 'set' accessor of property 'C.Q6' should use the backing 'field' because the other accessor is using it. - // public static partial object Q6 { get; set { } } = 6; - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.Q6").WithLocation(15, 44), // (16,39): warning CS9265: The 'get' accessor of property 'C.Q7' should use the backing 'field' because the other accessor is using it. // public static partial object Q7 { get => null; set; } = 7; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Q7").WithLocation(16, 39)); From 6b95474dde8f5e6ed25ee14baef96c4629c3fadd Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 10 Oct 2024 15:44:43 -0700 Subject: [PATCH 5/7] Address some feedback --- .../CSharp/Portable/CSharpResources.resx | 4 +- .../Source/SourcePropertySymbolBase.cs | 14 +- .../Portable/xlf/CSharpResources.cs.xlf | 8 +- .../Portable/xlf/CSharpResources.de.xlf | 8 +- .../Portable/xlf/CSharpResources.es.xlf | 8 +- .../Portable/xlf/CSharpResources.fr.xlf | 8 +- .../Portable/xlf/CSharpResources.it.xlf | 8 +- .../Portable/xlf/CSharpResources.ja.xlf | 8 +- .../Portable/xlf/CSharpResources.ko.xlf | 8 +- .../Portable/xlf/CSharpResources.pl.xlf | 8 +- .../Portable/xlf/CSharpResources.pt-BR.xlf | 8 +- .../Portable/xlf/CSharpResources.ru.xlf | 8 +- .../Portable/xlf/CSharpResources.tr.xlf | 8 +- .../Portable/xlf/CSharpResources.zh-Hans.xlf | 8 +- .../Portable/xlf/CSharpResources.zh-Hant.xlf | 8 +- .../Test/Emit3/Attributes/AttributeTests.cs | 2 +- .../Attributes/AttributeTests_Locations.cs | 4 +- .../CSharp/Test/Emit3/FieldKeywordTests.cs | 307 +++++++++--------- .../DefaultInterfaceImplementationTests.cs | 12 +- .../Symbol/Symbols/PartialPropertiesTests.cs | 6 +- .../Test/Symbol/Symbols/SymbolErrorTests.cs | 4 +- 21 files changed, 228 insertions(+), 229 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index adfe1b8f65ac1..886717e2c4ac4 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -8000,9 +8000,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Non-nullable property must contain a non-null value when exiting constructor. Consider adding the 'required' modifier, or declaring the property as nullable, or adding '[field: MaybeNull, AllowNull]' attributes. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs index b44dbc902298f..ba33220db5222 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs @@ -31,13 +31,13 @@ private enum Flags : ushort IsExpressionBodied = 1 << 0, HasAutoPropertyGet = 1 << 1, HasAutoPropertySet = 1 << 2, - GetterUsesFieldKeyword = 1 << 4, - SetterUsesFieldKeyword = 1 << 5, - IsExplicitInterfaceImplementation = 1 << 6, - HasInitializer = 1 << 7, - AccessorsHaveImplementation = 1 << 8, - HasExplicitAccessModifier = 1 << 9, - RequiresBackingField = 1 << 10, + GetterUsesFieldKeyword = 1 << 3, + SetterUsesFieldKeyword = 1 << 4, + IsExplicitInterfaceImplementation = 1 << 5, + HasInitializer = 1 << 6, + AccessorsHaveImplementation = 1 << 7, + HasExplicitAccessModifier = 1 << 8, + RequiresBackingField = 1 << 9, } // TODO (tomat): consider splitting into multiple subclasses/rare data. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 0e0acf35591ea..372d20af91d59 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index da5a3df321bca..6dd4f2b34ba85 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 04ad6bc9ba3fb..5bc0beea904d1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 10257ff4b43e0..080a42d09fa5f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 8a586894001c9..1fa46b045c4b2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index cc2219d3a6610..cd80ffa97f965 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 7f602276f9bd7..85d16196ea718 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 564c8a22f50b8..0ca7ee19074b4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index c892fcc5ceb1d..5b190f3f43891 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 836df68d34b77..c31ad6bd153ff 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 23694b30dc46c..d9624916fd86b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index d88ebfb42ba2b..d1fa418ee5e46 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 6f29cab199507..056b2e5a928e1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2658,13 +2658,13 @@ - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. - The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. + The '{0}' accessor of property '{1}' should use 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. - Property accessor should use the backing 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. + Property accessor should use 'field' because the other accessor is using it. diff --git a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs index 5a6a2f49e8a88..f3e9dc9afbd6f 100644 --- a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs @@ -2396,7 +2396,7 @@ public class Test // (6,21): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. // public int P { [field: A] get => throw null; set => throw null; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, return").WithLocation(6, 21), - // (6,50): warning CS9265: The 'set' accessor of property 'Test.P' should use the backing 'field' because the other accessor is using it. + // (6,50): warning CS9265: The 'set' accessor of property 'Test.P' should use 'field' because the other accessor is using it. // public int P { [field: A] get => throw null; set => throw null; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "Test.P").WithLocation(6, 50), // (7,22): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. diff --git a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs index 3684f2d7c6330..45fe578dc34ba 100644 --- a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs +++ b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs @@ -632,7 +632,7 @@ int Goo } "; CreateCompilation(source).VerifyDiagnostics( - // (25,9): warning CS9265: The 'set' accessor of property 'C.Goo' should use the backing 'field' because the other accessor is using it. + // (25,9): warning CS9265: The 'set' accessor of property 'C.Goo' should use 'field' because the other accessor is using it. // set { } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.Goo").WithLocation(25, 9), // (12,10): warning CS0657: 'assembly' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. @@ -696,7 +696,7 @@ int Goo } "; CreateCompilation(source).VerifyDiagnostics( - // (11,9): warning CS9265: The 'get' accessor of property 'C.Goo' should use the backing 'field' because the other accessor is using it. + // (11,9): warning CS9265: The 'get' accessor of property 'C.Goo' should use 'field' because the other accessor is using it. // get { return 0; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Goo").WithLocation(11, 9), // (14,10): warning CS0657: 'assembly' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. diff --git a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs index e33457b162435..d5bf2812b4d42 100644 --- a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs @@ -215,10 +215,10 @@ object P4 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use 'field' because the other accessor is using it. // get { return _field; } // 1 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(6, 9), - // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. + // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use 'field' because the other accessor is using it. // set { _field = value; } // 2 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(13, 9)); } @@ -245,10 +245,10 @@ object P2 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: The 'get' accessor of property 'C.P1' should use 'field' because the other accessor is using it. // get { return _field; } // 1 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(6, 9), - // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. + // (13,9): warning CS9265: The 'set' accessor of property 'C.P2' should use 'field' because the other accessor is using it. // set { _field = value; } // 2 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(13, 9)); } @@ -277,10 +277,10 @@ partial object P2 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (7,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // (7,9): warning CS9265: The 'get' accessor of property 'C.P1' should use 'field' because the other accessor is using it. // get { return _field; } // 1 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(7, 9), - // (15,9): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. + // (15,9): warning CS9265: The 'set' accessor of property 'C.P2' should use 'field' because the other accessor is using it. // set { _field = value; } // 2 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(15, 9)); } @@ -324,10 +324,10 @@ partial object P4 """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (8,9): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // (8,9): warning CS9265: The 'get' accessor of property 'C.P1' should use 'field' because the other accessor is using it. // get { return _field; } // 1 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(8, 9), - // (22,9): warning CS9265: The 'get' accessor of property 'C.P3' should use the backing 'field' because the other accessor is using it. + // (22,9): warning CS9265: The 'get' accessor of property 'C.P3' should use 'field' because the other accessor is using it. // get { return _field; } // 2 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P3").WithLocation(22, 9)); } @@ -359,10 +359,10 @@ class ReadonlyC3 : I """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (8,31): warning CS9265: The 'set' accessor of property 'ReadonlyC1.Prop' should use the backing 'field' because the other accessor is using it. + // (8,31): warning CS9265: The 'set' accessor of property 'ReadonlyC1.Prop' should use 'field' because the other accessor is using it. // public string Prop { get; set => throw null!; } // 1 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "ReadonlyC1.Prop").WithLocation(8, 31), - // (18,26): warning CS9265: The 'get' accessor of property 'ReadonlyC3.Prop' should use the backing 'field' because the other accessor is using it. + // (18,26): warning CS9265: The 'get' accessor of property 'ReadonlyC3.Prop' should use 'field' because the other accessor is using it. // public string Prop { get => throw null!; set; } = null!; // 2 Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "ReadonlyC3.Prop").WithLocation(18, 26)); } @@ -383,7 +383,7 @@ object P """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,9): warning CS9265: The 'get' accessor of property 'C.P' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: The 'get' accessor of property 'C.P' should use 'field' because the other accessor is using it. // get { return _other.field; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P").WithLocation(6, 9), // (6,29): error CS1061: 'C' does not contain a definition for 'field' and no accessible extension method 'field' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) @@ -406,7 +406,7 @@ C P """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,9): warning CS9265: The 'get' accessor of property 'C.P' should use the backing 'field' because the other accessor is using it. + // (5,9): warning CS9265: The 'get' accessor of property 'C.P' should use 'field' because the other accessor is using it. // get { return null; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P").WithLocation(5, 9), // (6,29): error CS1061: 'C' does not contain a definition for 'field' and no accessible extension method 'field' accepting a first argument of type 'C' could be found (are you missing a using directive or an assembly reference?) @@ -439,7 +439,7 @@ int P """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,9): warning CS9265: The 'set' accessor of property 'C.P' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: The 'set' accessor of property 'C.P' should use 'field' because the other accessor is using it. // set { _ = this is { field: 0 }; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P").WithLocation(6, 9), // (6,29): error CS0117: 'C' does not contain a definition for 'field' @@ -998,13 +998,13 @@ interface I // (5,12): error CS0525: Interfaces cannot contain instance fields // object Q3 { get; set { } } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "Q3").WithLocation(5, 12), - // (5,22): warning CS9265: The 'set' accessor of property 'I.Q3' should use the backing 'field' because the other accessor is using it. + // (5,22): warning CS9265: The 'set' accessor of property 'I.Q3' should use 'field' because the other accessor is using it. // object Q3 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, useInit ? "init" : "set").WithArguments(useInit ? "init" : "set", "I.Q3").WithLocation(5, 22), // (6,12): error CS0525: Interfaces cannot contain instance fields // object Q4 { get { return null; } set ; } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "Q4").WithLocation(6, 12), - // (6,17): warning CS9265: The 'get' accessor of property 'I.Q4' should use the backing 'field' because the other accessor is using it. + // (6,17): warning CS9265: The 'get' accessor of property 'I.Q4' should use 'field' because the other accessor is using it. // object Q4 { get { return null; } set ; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.Q4").WithLocation(6, 17)); } @@ -1309,10 +1309,10 @@ class C // (8,20): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // object P1 { [A(field)] get { return null; } set { } } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(8, 20), - // (8,49): warning CS9265: The 'set' accessor of property 'B.P1' should use the backing 'field' because the other accessor is using it. + // (8,49): warning CS9265: The 'set' accessor of property 'B.P1' should use 'field' because the other accessor is using it. // object P1 { [A(field)] get { return null; } set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.P1").WithLocation(8, 49), - // (9,17): warning CS9265: The 'get' accessor of property 'B.P2' should use the backing 'field' because the other accessor is using it. + // (9,17): warning CS9265: The 'get' accessor of property 'B.P2' should use 'field' because the other accessor is using it. // object P2 { get { return null; } [A(field)] set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P2").WithLocation(9, 17), // (9,41): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type @@ -1324,7 +1324,7 @@ class C // (14,20): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // object P3 { [A(field)] get { return null; } set { } } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(14, 20), - // (14,49): warning CS9265: The 'set' accessor of property 'C.P3' should use the backing 'field' because the other accessor is using it. + // (14,49): warning CS9265: The 'set' accessor of property 'C.P3' should use 'field' because the other accessor is using it. // object P3 { [A(field)] get { return null; } set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P3").WithLocation(14, 49)); @@ -1404,10 +1404,10 @@ static void ReportMember(MemberInfo member) // (18,37): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. // public static object P5 { get; [field: A(5)] set; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, param, return").WithLocation(18, 37), - // (20,81): warning CS9265: The 'set' accessor of property 'B.Q2' should use the backing 'field' because the other accessor is using it. + // (20,81): warning CS9265: The 'set' accessor of property 'B.Q2' should use 'field' because the other accessor is using it. // [field: A(2)][field: A(-2)] public static object Q2 { get { return field; } set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.Q2").WithLocation(20, 81), - // (21,60): warning CS9265: The 'init' accessor of property 'B.Q3' should use the backing 'field' because the other accessor is using it. + // (21,60): warning CS9265: The 'init' accessor of property 'B.Q3' should use 'field' because the other accessor is using it. // [field: A(3)] public object Q3 { get { return field; } init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "B.Q3").WithLocation(21, 60), // (22,25): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. @@ -1498,16 +1498,16 @@ static void ReportMember(MemberInfo member) C.k__BackingField: System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.ObsoleteAttribute, """); verifier.VerifyDiagnostics( - // (5,63): warning CS9265: The 'set' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // (5,63): warning CS9265: The 'set' accessor of property 'C.P1' should use 'field' because the other accessor is using it. // [Obsolete] public static object P1 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P1").WithLocation(5, 63), - // (6,63): warning CS9265: The 'set' accessor of property 'C.P2' should use the backing 'field' because the other accessor is using it. + // (6,63): warning CS9265: The 'set' accessor of property 'C.P2' should use 'field' because the other accessor is using it. // [field: Obsolete] public static object P2 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P2").WithLocation(6, 63), - // (7,56): warning CS9265: The 'set' accessor of property 'C.P3' should use the backing 'field' because the other accessor is using it. + // (7,56): warning CS9265: The 'set' accessor of property 'C.P3' should use 'field' because the other accessor is using it. // [Obsolete] public object P3 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P3").WithLocation(7, 56), - // (8,56): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // (8,56): warning CS9265: The 'set' accessor of property 'C.P4' should use 'field' because the other accessor is using it. // [field: Obsolete] public object P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(8, 56), // (15,13): warning CS0612: 'C.P1' is obsolete @@ -1556,7 +1556,7 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(1, 2, 3, 4, 0, 6, 7, 9)")); verifier.VerifyDiagnostics( - // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use 'field' because the other accessor is using it. // public static int P5 { get => 0; set; } = 5; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28)); verifier.VerifyIL("C..cctor", """ @@ -1648,7 +1648,7 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(1, 2, 3, 4, 0, 6, 7, 9)")); verifier.VerifyDiagnostics( - // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use 'field' because the other accessor is using it. // public static int P5 { get => 0; set; } = 5; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28)); verifier.VerifyIL("C..cctor", """ @@ -1712,7 +1712,7 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(useInit, "(1, 2, 3, 4, 0, 6, 7, 9)")); verifier.VerifyDiagnostics( - // (8,21): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // (8,21): warning CS9265: The 'get' accessor of property 'C.P5' should use 'field' because the other accessor is using it. // public int P5 { get => 0; set; } = 5; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 21)); verifier.VerifyIL("C..ctor", """ @@ -1820,7 +1820,7 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(useInit, "(1, 2, 3, 4, 0, 6, 7, 9)")); verifier.VerifyDiagnostics( - // (8,21): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // (8,21): warning CS9265: The 'get' accessor of property 'C.P5' should use 'field' because the other accessor is using it. // public int P5 { get => 0; set; } = 5; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 21)); verifier.VerifyIL("C..ctor", """ @@ -1927,7 +1927,7 @@ interface I // (8,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P5 { get => 0; set; } = 5; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P5").WithLocation(8, 16), - // (8,21): warning CS9265: The 'get' accessor of property 'I.P5' should use the backing 'field' because the other accessor is using it. + // (8,21): warning CS9265: The 'get' accessor of property 'I.P5' should use 'field' because the other accessor is using it. // public int P5 { get => 0; set; } = 5; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P5").WithLocation(8, 21), // (9,16): error CS8053: Instance properties in interfaces cannot have initializers. @@ -1941,8 +1941,7 @@ interface I Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P8").WithLocation(11, 16), // (12,16): error CS8053: Instance properties in interfaces cannot have initializers. // public int P9 { get { return field; } set { field = value; } } = 9; - Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P9").WithLocation(12, 16) - ); + Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P9").WithLocation(12, 16)); var containingType = comp.GetMember("I"); var actualFields = containingType.GetMembers().OfType().ToImmutableArray(); @@ -2054,13 +2053,13 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(0, 0, 3, 0, 0, 6, 0, 9)")); verifier.VerifyDiagnostics( - // (7,42): warning CS9265: The 'set' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. + // (7,42): warning CS9265: The 'set' accessor of property 'I.P4' should use 'field' because the other accessor is using it. // static int P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P4").WithLocation(7, 42), - // (8,28): warning CS9265: The 'get' accessor of property 'I.P5' should use the backing 'field' because the other accessor is using it. + // (8,28): warning CS9265: The 'get' accessor of property 'I.P5' should use 'field' because the other accessor is using it. // static int P5 { get => 0; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P5").WithLocation(8, 28), - // (10,33): warning CS9265: The 'set' accessor of property 'I.P7' should use the backing 'field' because the other accessor is using it. + // (10,33): warning CS9265: The 'set' accessor of property 'I.P7' should use 'field' because the other accessor is using it. // static int P7 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P7").WithLocation(10, 33)); @@ -2127,19 +2126,19 @@ interface I // (6,16): error CS0525: Interfaces cannot contain instance fields // int P4 { get => field; set { } } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P4").WithLocation(6, 16), - // (6,35): warning CS9265: The 'set' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. + // (6,35): warning CS9265: The 'set' accessor of property 'I.P4' should use 'field' because the other accessor is using it. // int P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "I.P4").WithLocation(6, 35), // (7,16): error CS0525: Interfaces cannot contain instance fields // int P5 { get => 0; set; } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P5").WithLocation(7, 16), - // (7,21): warning CS9265: The 'get' accessor of property 'I.P5' should use the backing 'field' because the other accessor is using it. + // (7,21): warning CS9265: The 'get' accessor of property 'I.P5' should use 'field' because the other accessor is using it. // int P5 { get => 0; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P5").WithLocation(7, 21), // (9,16): error CS0525: Interfaces cannot contain instance fields // int P7 { get; set { } } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P7").WithLocation(9, 16), - // (9,26): warning CS9265: The 'set' accessor of property 'I.P7' should use the backing 'field' because the other accessor is using it. + // (9,26): warning CS9265: The 'set' accessor of property 'I.P7' should use 'field' because the other accessor is using it. // int P7 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "I.P7").WithLocation(9, 26), // (10,16): error CS0525: Interfaces cannot contain instance fields @@ -2264,13 +2263,13 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("(1, 2, 3, 0, 0, 6, 0, 9)")); verifier.VerifyDiagnostics( - // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use 'field' because the other accessor is using it. // public static int P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42), - // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use the backing 'field' because the other accessor is using it. + // (8,28): warning CS9265: The 'get' accessor of property 'C.P5' should use 'field' because the other accessor is using it. // public static int P5 { get => 0; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P5").WithLocation(8, 28), - // (10,33): warning CS9265: The 'set' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. + // (10,33): warning CS9265: The 'set' accessor of property 'C.P7' should use 'field' because the other accessor is using it. // public static int P7 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P7").WithLocation(10, 33)); verifier.VerifyIL("C..cctor", """ @@ -2393,13 +2392,13 @@ static void Main() verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(useInit, "(1, 2, 3, 0, 0, 6, 0, 9)")); verifier.VerifyDiagnostics( - // (27,35): warning CS9265: The 'set' accessor of property 'C4.P4' should use the backing 'field' because the other accessor is using it. + // (27,35): warning CS9265: The 'set' accessor of property 'C4.P4' should use 'field' because the other accessor is using it. // public int P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C4.P4").WithLocation(27, 35), - // (34,21): warning CS9265: The 'get' accessor of property 'C5.P5' should use the backing 'field' because the other accessor is using it. + // (34,21): warning CS9265: The 'get' accessor of property 'C5.P5' should use 'field' because the other accessor is using it. // public int P5 { get => default; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C5.P5").WithLocation(34, 21), - // (48,26): warning CS9265: The 'set' accessor of property 'C7.P7' should use the backing 'field' because the other accessor is using it. + // (48,26): warning CS9265: The 'set' accessor of property 'C7.P7' should use 'field' because the other accessor is using it. // public int P7 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C7.P7").WithLocation(48, 26)); if (typeKind == "class") @@ -3717,10 +3716,10 @@ static B() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,50): warning CS9265: The 'set' accessor of property 'A.P5' should use the backing 'field' because the other accessor is using it. + // (6,50): warning CS9265: The 'set' accessor of property 'A.P5' should use 'field' because the other accessor is using it. // public static int P5 { get => field; private set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "A.P5").WithLocation(6, 50), - // (7,41): warning CS9265: The 'set' accessor of property 'A.P7' should use the backing 'field' because the other accessor is using it. + // (7,41): warning CS9265: The 'set' accessor of property 'A.P7' should use 'field' because the other accessor is using it. // public static int P7 { get; private set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "A.P7").WithLocation(7, 41), // (13,9): error CS0272: The property or indexer 'A.P1' cannot be used in this context because the set accessor is inaccessible @@ -3770,16 +3769,16 @@ public B() """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // (8,43): warning CS9265: The 'set' accessor of property 'A.P5' should use the backing 'field' because the other accessor is using it. + // (8,43): warning CS9265: The 'set' accessor of property 'A.P5' should use 'field' because the other accessor is using it. // public int P5 { get => field; private set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "A.P5").WithLocation(8, 43), - // (9,43): warning CS9265: The 'init' accessor of property 'A.P6' should use the backing 'field' because the other accessor is using it. + // (9,43): warning CS9265: The 'init' accessor of property 'A.P6' should use 'field' because the other accessor is using it. // public int P6 { get => field; private init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "A.P6").WithLocation(9, 43), - // (10,34): warning CS9265: The 'set' accessor of property 'A.P7' should use the backing 'field' because the other accessor is using it. + // (10,34): warning CS9265: The 'set' accessor of property 'A.P7' should use 'field' because the other accessor is using it. // public int P7 { get; private set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "A.P7").WithLocation(10, 34), - // (11,34): warning CS9265: The 'init' accessor of property 'A.P8' should use the backing 'field' because the other accessor is using it. + // (11,34): warning CS9265: The 'init' accessor of property 'A.P8' should use 'field' because the other accessor is using it. // public int P8 { get; private init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "A.P8").WithLocation(11, 34), // (17,9): error CS0272: The property or indexer 'A.P1' cannot be used in this context because the set accessor is inaccessible @@ -3887,7 +3886,7 @@ static void Main() """; var verifier = CompileAndVerify(source, expectedOutput: "(1, 2, 3, 0)"); verifier.VerifyDiagnostics( - // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use the backing 'field' because the other accessor is using it. + // (7,42): warning CS9265: The 'set' accessor of property 'C.P4' should use 'field' because the other accessor is using it. // public static int P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P4").WithLocation(7, 42)); verifier.VerifyIL("C..cctor", """ @@ -4477,16 +4476,16 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use if (useInit) { comp.VerifyEmitDiagnostics( - // (6,40): warning CS9265: The 'init' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // (6,40): warning CS9265: The 'init' accessor of property 'S.P4' should use 'field' because the other accessor is using it. // object P4 { get => field; init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.P4").WithLocation(6, 40), - // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // object P6 { get => null; init; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(8, 26), - // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // object P8 { get => null; init { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), - // (12,31): warning CS9265: The 'init' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // (12,31): warning CS9265: The 'init' accessor of property 'S.PA' should use 'field' because the other accessor is using it. // object PA { get; init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.PA").WithLocation(12, 31)); } @@ -4496,22 +4495,22 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use // (5,21): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P3 { get => field; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P3").WithLocation(5, 21), - // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use 'field' because the other accessor is using it. // object P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(6, 40), // (8,21): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P6 { get => null; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P6").WithLocation(8, 21), - // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // object P6 { get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(8, 26), - // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // object P8 { get => null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), // (11,21): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P9 { get; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P9").WithLocation(11, 21), - // (12,31): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // (12,31): warning CS9265: The 'set' accessor of property 'S.PA' should use 'field' because the other accessor is using it. // object PA { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(12, 31), // (14,37): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) @@ -4527,22 +4526,22 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use // (5,21): error CS8659: Auto-implemented property 'S.P3' cannot be marked 'readonly' because it has a 'set' accessor. // readonly object P3 { get => field; set; } Diagnostic(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, "P3").WithArguments("S.P3").WithLocation(5, 21), - // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use 'field' because the other accessor is using it. // readonly object P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(6, 40), // (8,21): error CS8659: Auto-implemented property 'S.P6' cannot be marked 'readonly' because it has a 'set' accessor. // readonly object P6 { get => null; set; } Diagnostic(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, "P6").WithArguments("S.P6").WithLocation(8, 21), - // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // readonly object P6 { get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(8, 26), - // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // readonly object P8 { get => null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), // (11,21): error CS8659: Auto-implemented property 'S.P9' cannot be marked 'readonly' because it has a 'set' accessor. // readonly object P9 { get; set; } Diagnostic(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, "P9").WithArguments("S.P9").WithLocation(11, 21), - // (12,31): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // (12,31): warning CS9265: The 'set' accessor of property 'S.PA' should use 'field' because the other accessor is using it. // readonly object PA { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(12, 31), // (14,37): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) @@ -4555,16 +4554,16 @@ public void ReadOnly_01(bool useReadOnlyType, bool useReadOnlyProperty, bool use else { comp.VerifyEmitDiagnostics( - // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // (6,40): warning CS9265: The 'set' accessor of property 'S.P4' should use 'field' because the other accessor is using it. // object P4 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(6, 40), - // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (8,26): warning CS9265: The 'get' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // object P6 { get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(8, 26), - // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (10,26): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // object P8 { get => null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 26), - // (12,31): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // (12,31): warning CS9265: The 'set' accessor of property 'S.PA' should use 'field' because the other accessor is using it. // object PA { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(12, 31)); } @@ -4616,22 +4615,22 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (3,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P3 { readonly get => field; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P3").WithLocation(3, 12), - // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use 'field' because the other accessor is using it. // object P4 { readonly get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), // (5,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P6 { readonly get => null; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P6").WithLocation(5, 12), - // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // object P6 { readonly get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(5, 26), - // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // object P8 { readonly get => null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26), // (8,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P9 { readonly get; set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P9").WithLocation(8, 12), - // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use 'field' because the other accessor is using it. // object PA { readonly get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(9, 40), // (10,46): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) @@ -4647,19 +4646,19 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (3,49): error CS8658: Auto-implemented 'set' accessor 'S.P3.set' cannot be marked 'readonly'. // object P3 { get => field; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P3.set").WithLocation(3, 49), - // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use 'field' because the other accessor is using it. // object P4 { get => field; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), // (5,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.ERR_AutoPropsInRoStruct, "P6").WithLocation(5, 12), - // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(5, 26), // (5,48): error CS8658: Auto-implemented 'set' accessor 'S.P6.set' cannot be marked 'readonly'. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P6.set").WithLocation(5, 48), - // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // object P8 { get => null; readonly set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26), // (8,12): error CS8341: Auto-implemented instance properties in readonly structs must be readonly. @@ -4668,7 +4667,7 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (8,40): error CS8658: Auto-implemented 'set' accessor 'S.P9.set' cannot be marked 'readonly'. // object P9 { get; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P9.set").WithLocation(8, 40), - // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use 'field' because the other accessor is using it. // object PA { get; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(9, 40), // (10,46): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) @@ -4681,16 +4680,16 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) if (useReadOnlyOnGet) { comp.VerifyEmitDiagnostics( - // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use 'field' because the other accessor is using it. // object P4 { readonly get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), - // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // object P6 { readonly get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(5, 26), - // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // object P8 { readonly get => null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26), - // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use 'field' because the other accessor is using it. // object PA { readonly get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(9, 40)); } @@ -4700,22 +4699,22 @@ public void ReadOnly_02(bool useReadOnlyType, bool useReadOnlyOnGet) // (3,49): error CS8658: Auto-implemented 'set' accessor 'S.P3.set' cannot be marked 'readonly'. // object P3 { get => field; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P3.set").WithLocation(3, 49), - // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use the backing 'field' because the other accessor is using it. + // (4,49): warning CS9265: The 'set' accessor of property 'S.P4' should use 'field' because the other accessor is using it. // object P4 { get => field; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P4").WithLocation(4, 49), - // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (5,26): warning CS9265: The 'get' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P6").WithLocation(5, 26), // (5,48): error CS8658: Auto-implemented 'set' accessor 'S.P6.set' cannot be marked 'readonly'. // object P6 { get => null; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P6.set").WithLocation(5, 48), - // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (7,26): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // object P8 { get => null; readonly set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(7, 26), // (8,40): error CS8658: Auto-implemented 'set' accessor 'S.P9.set' cannot be marked 'readonly'. // object P9 { get; readonly set; } Diagnostic(ErrorCode.ERR_AutoSetterCantBeReadOnly, "set").WithArguments("S.P9.set").WithLocation(8, 40), - // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use the backing 'field' because the other accessor is using it. + // (9,40): warning CS9265: The 'set' accessor of property 'S.PA' should use 'field' because the other accessor is using it. // object PA { get; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PA").WithLocation(9, 40), // (10,46): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer) @@ -4945,7 +4944,7 @@ struct S // (11,31): error CS8903: 'init' accessors cannot be marked 'readonly'. Mark 'S.Q4' readonly instead. // object Q4 { get; readonly init { } } Diagnostic(ErrorCode.ERR_InitCannotBeReadonly, "init").WithArguments("S.Q4").WithLocation(11, 31), - // (11,31): warning CS9265: The 'init' accessor of property 'S.Q4' should use the backing 'field' because the other accessor is using it. + // (11,31): warning CS9265: The 'init' accessor of property 'S.Q4' should use 'field' because the other accessor is using it. // object Q4 { get; readonly init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.Q4").WithLocation(11, 31), // (12,12): error CS8661: Cannot specify 'readonly' modifiers on both accessors of property or indexer 'S.Q5'. Instead, put a 'readonly' modifier on the property itself. @@ -4954,7 +4953,7 @@ struct S // (12,49): error CS8903: 'init' accessors cannot be marked 'readonly'. Mark 'S.Q5' readonly instead. // object Q5 { readonly get => field; readonly init { } } Diagnostic(ErrorCode.ERR_InitCannotBeReadonly, "init").WithArguments("S.Q5").WithLocation(12, 49), - // (12,49): warning CS9265: The 'init' accessor of property 'S.Q5' should use the backing 'field' because the other accessor is using it. + // (12,49): warning CS9265: The 'init' accessor of property 'S.Q5' should use 'field' because the other accessor is using it. // object Q5 { readonly get => field; readonly init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.Q5").WithLocation(12, 49)); } @@ -4988,13 +4987,13 @@ struct S // (9,12): error CS8664: 'S.Q2': 'readonly' can only be used on accessors if the property or indexer has both a get and a set accessor // object Q2 { readonly set { _ = field; } } Diagnostic(ErrorCode.ERR_ReadOnlyModMissingAccessor, "Q2").WithArguments("S.Q2").WithLocation(9, 12), - // (11,31): warning CS9265: The 'set' accessor of property 'S.Q4' should use the backing 'field' because the other accessor is using it. + // (11,31): warning CS9265: The 'set' accessor of property 'S.Q4' should use 'field' because the other accessor is using it. // object Q4 { get; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.Q4").WithLocation(11, 31), // (12,12): error CS8661: Cannot specify 'readonly' modifiers on both accessors of property or indexer 'S.Q5'. Instead, put a 'readonly' modifier on the property itself. // object Q5 { readonly get => field; readonly set { } } Diagnostic(ErrorCode.ERR_DuplicatePropertyReadOnlyMods, "Q5").WithArguments("S.Q5").WithLocation(12, 12), - // (12,49): warning CS9265: The 'set' accessor of property 'S.Q5' should use the backing 'field' because the other accessor is using it. + // (12,49): warning CS9265: The 'set' accessor of property 'S.Q5' should use 'field' because the other accessor is using it. // object Q5 { readonly get => field; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.Q5").WithLocation(12, 49)); } @@ -5188,7 +5187,7 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (7,25): error CS8145: Auto-implemented properties cannot return by reference // ref object P5 { get => ref field; set { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P5").WithLocation(7, 25), - // (7,48): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // (7,48): warning CS9265: The 'set' accessor of property 'S.P5' should use 'field' because the other accessor is using it. // ref object P5 { get => ref field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 48), // (7,48): error CS8147: Properties which return by reference cannot have set accessors @@ -5197,7 +5196,7 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (8,25): error CS8145: Auto-implemented properties cannot return by reference // ref object P6 { get => ref field; init { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P6").WithLocation(8, 25), - // (8,48): warning CS9265: The 'init' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (8,48): warning CS9265: The 'init' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // ref object P6 { get => ref field; init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.P6").WithLocation(8, 48), // (8,48): error CS8147: Properties which return by reference cannot have set accessors @@ -5206,7 +5205,7 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (10,25): error CS8145: Auto-implemented properties cannot return by reference // ref object P8 { get => throw null; set; } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P8").WithLocation(10, 25), - // (10,30): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (10,30): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // ref object P8 { get => throw null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(10, 30), // (10,49): error CS8147: Properties which return by reference cannot have set accessors @@ -5215,7 +5214,7 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (11,25): error CS8145: Auto-implemented properties cannot return by reference // ref object P9 { get => throw null; init; } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P9").WithLocation(11, 25), - // (11,30): warning CS9265: The 'get' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // (11,30): warning CS9265: The 'get' accessor of property 'S.P9' should use 'field' because the other accessor is using it. // ref object P9 { get => throw null; init; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P9").WithLocation(11, 30), // (11,49): error CS8147: Properties which return by reference cannot have set accessors @@ -5224,7 +5223,7 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (12,25): error CS8145: Auto-implemented properties cannot return by reference // ref object PC { get => throw null; set { _ = field; } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PC").WithLocation(12, 25), - // (12,30): warning CS9265: The 'get' accessor of property 'S.PC' should use the backing 'field' because the other accessor is using it. + // (12,30): warning CS9265: The 'get' accessor of property 'S.PC' should use 'field' because the other accessor is using it. // ref object PC { get => throw null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.PC").WithLocation(12, 30), // (12,49): error CS8147: Properties which return by reference cannot have set accessors @@ -5233,7 +5232,7 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (13,25): error CS8145: Auto-implemented properties cannot return by reference // ref object PD { get => throw null; init { _ = field; } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PD").WithLocation(13, 25), - // (13,30): warning CS9265: The 'get' accessor of property 'S.PD' should use the backing 'field' because the other accessor is using it. + // (13,30): warning CS9265: The 'get' accessor of property 'S.PD' should use 'field' because the other accessor is using it. // ref object PD { get => throw null; init { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.PD").WithLocation(13, 30), // (13,49): error CS8147: Properties which return by reference cannot have set accessors @@ -5254,7 +5253,7 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (16,25): error CS8145: Auto-implemented properties cannot return by reference // ref object PG { get; set { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PG").WithLocation(16, 25), - // (16,35): warning CS9265: The 'set' accessor of property 'S.PG' should use the backing 'field' because the other accessor is using it. + // (16,35): warning CS9265: The 'set' accessor of property 'S.PG' should use 'field' because the other accessor is using it. // ref object PG { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PG").WithLocation(16, 35), // (16,35): error CS8147: Properties which return by reference cannot have set accessors @@ -5263,7 +5262,7 @@ public void RefReturning_01(bool useStruct, bool useRefReadOnly) // (17,25): error CS8145: Auto-implemented properties cannot return by reference // ref object PH { get; init { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PH").WithLocation(17, 25), - // (17,35): warning CS9265: The 'init' accessor of property 'S.PH' should use the backing 'field' because the other accessor is using it. + // (17,35): warning CS9265: The 'init' accessor of property 'S.PH' should use 'field' because the other accessor is using it. // ref object PH { get; init { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "init").WithArguments("init", "S.PH").WithLocation(17, 35), // (17,35): error CS8147: Properties which return by reference cannot have set accessors @@ -5321,7 +5320,7 @@ public void RefReturning_02(bool useStruct, bool useRefReadOnly) // (6,32): error CS8145: Auto-implemented properties cannot return by reference // static ref object P5 { get => ref field; set { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P5").WithLocation(6, 32), - // (6,55): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // (6,55): warning CS9265: The 'set' accessor of property 'S.P5' should use 'field' because the other accessor is using it. // static ref object P5 { get => ref field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(6, 55), // (6,55): error CS8147: Properties which return by reference cannot have set accessors @@ -5330,7 +5329,7 @@ public void RefReturning_02(bool useStruct, bool useRefReadOnly) // (8,32): error CS8145: Auto-implemented properties cannot return by reference // static ref object P8 { get => throw null; set; } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "P8").WithLocation(8, 32), - // (8,37): warning CS9265: The 'get' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (8,37): warning CS9265: The 'get' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // static ref object P8 { get => throw null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.P8").WithLocation(8, 37), // (8,56): error CS8147: Properties which return by reference cannot have set accessors @@ -5339,7 +5338,7 @@ public void RefReturning_02(bool useStruct, bool useRefReadOnly) // (9,32): error CS8145: Auto-implemented properties cannot return by reference // static ref object PC { get => throw null; set { _ = field; } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PC").WithLocation(9, 32), - // (9,37): warning CS9265: The 'get' accessor of property 'S.PC' should use the backing 'field' because the other accessor is using it. + // (9,37): warning CS9265: The 'get' accessor of property 'S.PC' should use 'field' because the other accessor is using it. // static ref object PC { get => throw null; set { _ = field; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "S.PC").WithLocation(9, 37), // (9,56): error CS8147: Properties which return by reference cannot have set accessors @@ -5354,7 +5353,7 @@ public void RefReturning_02(bool useStruct, bool useRefReadOnly) // (11,32): error CS8145: Auto-implemented properties cannot return by reference // static ref object PG { get; set { } } Diagnostic(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, "PG").WithLocation(11, 32), - // (11,42): warning CS9265: The 'set' accessor of property 'S.PG' should use the backing 'field' because the other accessor is using it. + // (11,42): warning CS9265: The 'set' accessor of property 'S.PG' should use 'field' because the other accessor is using it. // static ref object PG { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.PG").WithLocation(11, 42), // (11,42): error CS8147: Properties which return by reference cannot have set accessors @@ -5389,7 +5388,7 @@ struct S // (5,45): error CS1605: Cannot use 'field' as a ref or out value because it is read-only // object P3 { readonly get { return F(ref field); } set { } } Diagnostic(ErrorCode.ERR_RefReadonlyLocal, "field").WithArguments("field").WithLocation(5, 45), - // (5,55): warning CS9265: The 'set' accessor of property 'S.P3' should use the backing 'field' because the other accessor is using it. + // (5,55): warning CS9265: The 'set' accessor of property 'S.P3' should use 'field' because the other accessor is using it. // object P3 { readonly get { return F(ref field); } set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P3").WithLocation(5, 55)); } @@ -5409,7 +5408,7 @@ struct S """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // (5,54): warning CS9265: The 'set' accessor of property 'S.P3' should use the backing 'field' because the other accessor is using it. + // (5,54): warning CS9265: The 'set' accessor of property 'S.P3' should use 'field' because the other accessor is using it. // object P3 { readonly get { return F(in field); } set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P3").WithLocation(5, 54)); } @@ -5429,7 +5428,7 @@ struct S """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // (5,51): warning CS9265: The 'set' accessor of property 'S.P3' should use the backing 'field' because the other accessor is using it. + // (5,51): warning CS9265: The 'set' accessor of property 'S.P3' should use 'field' because the other accessor is using it. // object P3 { readonly get { return F(field); } set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P3").WithLocation(5, 51)); } @@ -5456,7 +5455,7 @@ struct S """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // (5,40): warning CS9265: The 'set' accessor of property 'S.P3' should use the backing 'field' because the other accessor is using it. + // (5,40): warning CS9265: The 'set' accessor of property 'S.P3' should use 'field' because the other accessor is using it. // object P3 { readonly get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P3").WithLocation(5, 40), // (9,15): error CS0206: A non ref-returning property or indexer may not be used as an out or ref value @@ -7501,25 +7500,25 @@ class C // (3,25): error CS8051: Auto-implemented properties must have get accessors. // object P02 { set; } Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, setter).WithLocation(3, 25), - // (8,30): warning CS9265: The 'set' accessor of property 'C.P13' should use the backing 'field' because the other accessor is using it. + // (8,30): warning CS9265: The 'set' accessor of property 'C.P13' should use 'field' because the other accessor is using it. // object P13 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P13").WithLocation(8, 30), - // (12,39): warning CS9265: The 'set' accessor of property 'C.P23' should use the backing 'field' because the other accessor is using it. + // (12,39): warning CS9265: The 'set' accessor of property 'C.P23' should use 'field' because the other accessor is using it. // object P23 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P23").WithLocation(12, 39), - // (15,25): warning CS9265: The 'get' accessor of property 'C.P32' should use the backing 'field' because the other accessor is using it. + // (15,25): warning CS9265: The 'get' accessor of property 'C.P32' should use 'field' because the other accessor is using it. // object P32 { get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P32").WithLocation(15, 25), - // (17,25): warning CS9265: The 'get' accessor of property 'C.P34' should use the backing 'field' because the other accessor is using it. + // (17,25): warning CS9265: The 'get' accessor of property 'C.P34' should use 'field' because the other accessor is using it. // object P34 { get => null; set { field = value; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P34").WithLocation(17, 25), - // (20,47): warning CS9265: The 'set' accessor of property 'C.P43' should use the backing 'field' because the other accessor is using it. + // (20,47): warning CS9265: The 'set' accessor of property 'C.P43' should use 'field' because the other accessor is using it. // object P43 { get { return field; } set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "C.P43").WithLocation(20, 47), - // (23,25): warning CS9265: The 'get' accessor of property 'C.P52' should use the backing 'field' because the other accessor is using it. + // (23,25): warning CS9265: The 'get' accessor of property 'C.P52' should use 'field' because the other accessor is using it. // object P52 { get { return null; } set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P52").WithLocation(23, 25), - // (25,25): warning CS9265: The 'get' accessor of property 'C.P54' should use the backing 'field' because the other accessor is using it. + // (25,25): warning CS9265: The 'get' accessor of property 'C.P54' should use 'field' because the other accessor is using it. // object P54 { get { return null; } set { field = value; } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P54").WithLocation(25, 25)); } @@ -7591,10 +7590,10 @@ class B2 : A """; comp = CreateCompilation([sourceA, sourceB2], targetFramework: targetFramework); comp.VerifyEmitDiagnostics( - // (3,47): warning CS9265: The 'set' accessor of property 'B2.P1' should use the backing 'field' because the other accessor is using it. + // (3,47): warning CS9265: The 'set' accessor of property 'B2.P1' should use 'field' because the other accessor is using it. // public override object P1 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P1").WithLocation(3, 47), - // (4,47): warning CS9265: The 'set' accessor of property 'B2.P2' should use the backing 'field' because the other accessor is using it. + // (4,47): warning CS9265: The 'set' accessor of property 'B2.P2' should use 'field' because the other accessor is using it. // public override object P2 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P2").WithLocation(4, 47), // (4,47): error CS0546: 'B2.P2.set': cannot override because 'A.P2' does not have an overridable set accessor @@ -7606,7 +7605,7 @@ class B2 : A // (5,33): error CS0545: 'B2.P3.get': cannot override because 'A.P3' does not have an overridable get accessor // public override object P3 { get => field; set { } } Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("B2.P3.get", "A.P3").WithLocation(5, 33), - // (5,47): warning CS9265: The 'set' accessor of property 'B2.P3' should use the backing 'field' because the other accessor is using it. + // (5,47): warning CS9265: The 'set' accessor of property 'B2.P3' should use 'field' because the other accessor is using it. // public override object P3 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P3").WithLocation(5, 47)); @@ -7724,10 +7723,10 @@ class B2 : A """; comp = CreateCompilation([sourceA, sourceB2], targetFramework: targetFramework); comp.VerifyEmitDiagnostics( - // (3,47): warning CS9265: The 'set' accessor of property 'B2.P1' should use the backing 'field' because the other accessor is using it. + // (3,47): warning CS9265: The 'set' accessor of property 'B2.P1' should use 'field' because the other accessor is using it. // public override object P1 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P1").WithLocation(3, 47), - // (4,47): warning CS9265: The 'set' accessor of property 'B2.P2' should use the backing 'field' because the other accessor is using it. + // (4,47): warning CS9265: The 'set' accessor of property 'B2.P2' should use 'field' because the other accessor is using it. // public override object P2 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P2").WithLocation(4, 47), // (4,47): error CS0546: 'B2.P2.set': cannot override because 'A.P2' does not have an overridable set accessor @@ -7736,7 +7735,7 @@ class B2 : A // (5,33): error CS0545: 'B2.P3.get': cannot override because 'A.P3' does not have an overridable get accessor // public override object P3 { get => field; set { } } Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("B2.P3.get", "A.P3").WithLocation(5, 33), - // (5,47): warning CS9265: The 'set' accessor of property 'B2.P3' should use the backing 'field' because the other accessor is using it. + // (5,47): warning CS9265: The 'set' accessor of property 'B2.P3' should use 'field' because the other accessor is using it. // public override object P3 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P3").WithLocation(5, 47)); @@ -7841,13 +7840,13 @@ class B4 : A // (5,32): error CS8051: Auto-implemented properties must have get accessors. // public virtual object P3 { set; } Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, setter).WithLocation(5, 32), - // (21,42): warning CS9265: The 'set' accessor of property 'B2.P1' should use the backing 'field' because the other accessor is using it. + // (21,42): warning CS9265: The 'set' accessor of property 'B2.P1' should use 'field' because the other accessor is using it. // public new object P1 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P1").WithLocation(21, 42), - // (22,42): warning CS9265: The 'set' accessor of property 'B2.P2' should use the backing 'field' because the other accessor is using it. + // (22,42): warning CS9265: The 'set' accessor of property 'B2.P2' should use 'field' because the other accessor is using it. // public new object P2 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P2").WithLocation(22, 42), - // (23,42): warning CS9265: The 'set' accessor of property 'B2.P3' should use the backing 'field' because the other accessor is using it. + // (23,42): warning CS9265: The 'set' accessor of property 'B2.P3' should use 'field' because the other accessor is using it. // public new object P3 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, setter).WithArguments(setter, "B2.P3").WithLocation(23, 42)); } @@ -8046,7 +8045,7 @@ class C // (8,5): error CS0610: Field or property cannot be of type 'ArgIterator' // ArgIterator Q2 { get { return field; } set { } } Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "ArgIterator").WithArguments("System.ArgIterator").WithLocation(8, 5), - // (8,44): warning CS9265: The 'set' accessor of property 'C.Q2' should use the backing 'field' because the other accessor is using it. + // (8,44): warning CS9265: The 'set' accessor of property 'C.Q2' should use 'field' because the other accessor is using it. // ArgIterator Q2 { get { return field; } set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.Q2").WithLocation(8, 44)); } @@ -8533,13 +8532,13 @@ partial interface I // (3,20): error CS0525: Interfaces cannot contain instance fields // partial object P1 { get; set; } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(3, 20), - // (3,30): warning CS9265: The 'set' accessor of property 'I.P1' should use the backing 'field' because the other accessor is using it. + // (3,30): warning CS9265: The 'set' accessor of property 'I.P1' should use 'field' because the other accessor is using it. // partial object P1 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P1").WithLocation(3, 30), // (4,20): error CS0525: Interfaces cannot contain instance fields // partial object P2 { get; init; } Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P2").WithLocation(4, 20), - // (4,25): warning CS9265: The 'get' accessor of property 'I.P2' should use the backing 'field' because the other accessor is using it. + // (4,25): warning CS9265: The 'get' accessor of property 'I.P2' should use 'field' because the other accessor is using it. // partial object P2 { get => null; init; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P2").WithLocation(4, 25)); } @@ -8599,10 +8598,10 @@ partial interface I else { comp.VerifyEmitDiagnostics( - // (3,37): warning CS9265: The 'set' accessor of property 'I.P1' should use the backing 'field' because the other accessor is using it. + // (3,37): warning CS9265: The 'set' accessor of property 'I.P1' should use 'field' because the other accessor is using it. // static partial object P1 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I.P1").WithLocation(3, 37), - // (4,32): warning CS9265: The 'get' accessor of property 'I.P2' should use the backing 'field' because the other accessor is using it. + // (4,32): warning CS9265: The 'get' accessor of property 'I.P2' should use 'field' because the other accessor is using it. // static partial object P2 { get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P2").WithLocation(4, 32)); } @@ -8788,7 +8787,7 @@ partial interface I if (useStatic) { comp.VerifyEmitDiagnostics( - // (6,32): warning CS9265: The 'get' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. + // (6,32): warning CS9265: The 'get' accessor of property 'I.P4' should use 'field' because the other accessor is using it. // static partial object P4 { get => null; set { field = value; } } = 4; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P4").WithLocation(6, 32)); } @@ -8807,7 +8806,7 @@ partial interface I // (6,27): error CS8053: Instance properties in interfaces cannot have initializers. // partial object P4 { get => null; set { field = value; } } = 4; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P4").WithLocation(6, 27), - // (6,32): warning CS9265: The 'get' accessor of property 'I.P4' should use the backing 'field' because the other accessor is using it. + // (6,32): warning CS9265: The 'get' accessor of property 'I.P4' should use 'field' because the other accessor is using it. // partial object P4 { get => null; set { field = value; } } = 4; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I.P4").WithLocation(6, 32)); } @@ -9170,10 +9169,10 @@ static void Main() k__BackingField """)); verifier.VerifyDiagnostics( - // (9,39): warning CS9265: The 'get' accessor of property 'C.P7' should use the backing 'field' because the other accessor is using it. + // (9,39): warning CS9265: The 'get' accessor of property 'C.P7' should use 'field' because the other accessor is using it. // public static partial object P7 { get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P7").WithLocation(9, 39), - // (16,39): warning CS9265: The 'get' accessor of property 'C.Q7' should use the backing 'field' because the other accessor is using it. + // (16,39): warning CS9265: The 'get' accessor of property 'C.Q7' should use 'field' because the other accessor is using it. // public static partial object Q7 { get => null; set; } = 7; Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Q7").WithLocation(16, 39)); @@ -9550,19 +9549,19 @@ partial struct S { case (false, false): comp.VerifyEmitDiagnostics( - // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use 'field' because the other accessor is using it. // partial object P5 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 39), - // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // partial object P6 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P6").WithLocation(8, 39), - // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use the backing 'field' because the other accessor is using it. + // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use 'field' because the other accessor is using it. // partial object P7 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P7").WithLocation(9, 39), - // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // partial object P8 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), - // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use 'field' because the other accessor is using it. // partial object P9 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P9").WithLocation(11, 48)); break; @@ -9583,16 +9582,16 @@ partial struct S // (7,29): error CS8663: Both partial member declarations must be readonly or neither may be readonly // readonly partial object P5 { get; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "P5").WithLocation(7, 29), - // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use 'field' because the other accessor is using it. // readonly partial object P5 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 39), // (8,34): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P6 { readonly get; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "get").WithLocation(8, 34), - // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // partial object P6 { readonly get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P6").WithLocation(8, 39), - // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use the backing 'field' because the other accessor is using it. + // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use 'field' because the other accessor is using it. // partial object P7 { get; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P7").WithLocation(9, 39), // (9,39): error CS8663: Both partial member declarations must be readonly or neither may be readonly @@ -9601,10 +9600,10 @@ partial struct S // (10,34): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P8 { readonly get => field; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "get").WithLocation(10, 34), - // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // partial object P8 { readonly get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), - // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use 'field' because the other accessor is using it. // partial object P9 { get => field; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P9").WithLocation(11, 48), // (11,48): error CS8663: Both partial member declarations must be readonly or neither may be readonly @@ -9634,16 +9633,16 @@ partial struct S // (7,29): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P5 { get; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "P5").WithLocation(7, 29), - // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use 'field' because the other accessor is using it. // partial object P5 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 39), // (8,34): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P6 { get; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "get").WithLocation(8, 34), - // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // partial object P6 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P6").WithLocation(8, 39), - // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use the backing 'field' because the other accessor is using it. + // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use 'field' because the other accessor is using it. // partial object P7 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P7").WithLocation(9, 39), // (9,39): error CS8663: Both partial member declarations must be readonly or neither may be readonly @@ -9652,10 +9651,10 @@ partial struct S // (10,34): error CS8663: Both partial member declarations must be readonly or neither may be readonly // partial object P8 { get => field; set { } } Diagnostic(ErrorCode.ERR_PartialMemberReadOnlyDifference, "get").WithLocation(10, 34), - // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // partial object P8 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), - // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use 'field' because the other accessor is using it. // partial object P9 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P9").WithLocation(11, 48), // (11,48): error CS8663: Both partial member declarations must be readonly or neither may be readonly @@ -9670,19 +9669,19 @@ partial struct S // (6,20): error CS8664: 'S.P4': 'readonly' can only be used on accessors if the property or indexer has both a get and a set accessor // partial object P4 { readonly set; } Diagnostic(ErrorCode.ERR_ReadOnlyModMissingAccessor, "P4").WithArguments("S.P4").WithLocation(6, 20), - // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use the backing 'field' because the other accessor is using it. + // (7,39): warning CS9265: The 'set' accessor of property 'S.P5' should use 'field' because the other accessor is using it. // readonly partial object P5 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P5").WithLocation(7, 39), - // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use the backing 'field' because the other accessor is using it. + // (8,39): warning CS9265: The 'set' accessor of property 'S.P6' should use 'field' because the other accessor is using it. // partial object P6 { readonly get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P6").WithLocation(8, 39), - // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use the backing 'field' because the other accessor is using it. + // (9,39): warning CS9265: The 'set' accessor of property 'S.P7' should use 'field' because the other accessor is using it. // partial object P7 { get; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P7").WithLocation(9, 39), - // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use the backing 'field' because the other accessor is using it. + // (10,48): warning CS9265: The 'set' accessor of property 'S.P8' should use 'field' because the other accessor is using it. // partial object P8 { readonly get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P8").WithLocation(10, 48), - // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use the backing 'field' because the other accessor is using it. + // (11,48): warning CS9265: The 'set' accessor of property 'S.P9' should use 'field' because the other accessor is using it. // partial object P9 { get => field; readonly set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "S.P9").WithLocation(11, 48)); break; @@ -9749,7 +9748,7 @@ partial class B // (3,35): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // partial object P1 { [A(field)] get { return null; } } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(3, 35), - // (4,32): warning CS9265: The 'get' accessor of property 'B.P2' should use the backing 'field' because the other accessor is using it. + // (4,32): warning CS9265: The 'get' accessor of property 'B.P2' should use 'field' because the other accessor is using it. // partial object P2 { get { return null; } [A(field)] set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P2").WithLocation(4, 32), // (4,56): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type @@ -9823,7 +9822,7 @@ partial class B // (3,35): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // partial object P1 { [A(field)] get { return field; } } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(3, 35), - // (4,32): warning CS9265: The 'get' accessor of property 'B.P2' should use the backing 'field' because the other accessor is using it. + // (4,32): warning CS9265: The 'get' accessor of property 'B.P2' should use 'field' because the other accessor is using it. // partial object P2 { get { return null; } [A(field)] init; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P2").WithLocation(4, 32), // (4,56): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type @@ -9832,7 +9831,7 @@ partial class B // (5,35): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // partial object P3 { [A(field)] get; } Diagnostic(ErrorCode.ERR_BadAttributeArgument, "field").WithLocation(5, 35), - // (6,32): warning CS9265: The 'get' accessor of property 'B.P4' should use the backing 'field' because the other accessor is using it. + // (6,32): warning CS9265: The 'get' accessor of property 'B.P4' should use 'field' because the other accessor is using it. // partial object P4 { get { return null; } init; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P4").WithLocation(6, 32), // (6,40): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type @@ -9897,19 +9896,19 @@ partial class B // (3,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored. // [field: A] partial object P1 { get; set; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(3, 6), - // (4,50): warning CS9265: The 'set' accessor of property 'B.P2' should use the backing 'field' because the other accessor is using it. + // (4,50): warning CS9265: The 'set' accessor of property 'B.P2' should use 'field' because the other accessor is using it. // partial object P2 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.P2").WithLocation(4, 50), - // (5,36): warning CS9265: The 'get' accessor of property 'B.P3' should use the backing 'field' because the other accessor is using it. + // (5,36): warning CS9265: The 'get' accessor of property 'B.P3' should use 'field' because the other accessor is using it. // partial object P3 { get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.P3").WithLocation(5, 36), // (6,6): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'property'. All attributes in this block will be ignored. // [field: A] partial object Q1 { get => null; set { } } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "property").WithLocation(6, 6), - // (7,50): warning CS9265: The 'set' accessor of property 'B.Q2' should use the backing 'field' because the other accessor is using it. + // (7,50): warning CS9265: The 'set' accessor of property 'B.Q2' should use 'field' because the other accessor is using it. // [field: A] partial object Q2 { get => field; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.Q2").WithLocation(7, 50), - // (8,36): warning CS9265: The 'get' accessor of property 'B.Q3' should use the backing 'field' because the other accessor is using it. + // (8,36): warning CS9265: The 'get' accessor of property 'B.Q3' should use 'field' because the other accessor is using it. // [field: A] partial object Q3 { get => null; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "B.Q3").WithLocation(8, 36)); diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs index db8b84f835efb..10747c8761e2f 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs @@ -3383,7 +3383,7 @@ class Test1 : I1 break; case (true, false): compilation1.VerifyDiagnostics( - // (6,9): warning CS9265: The 'get' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: The 'get' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // get Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I1.P1").WithLocation(6, 9)); break; @@ -3403,7 +3403,7 @@ class Test1 : I1 // (4,9): error CS0525: Interfaces cannot contain instance fields // int P1 Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9), - // (6,9): warning CS9265: The 'get' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: The 'get' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // get Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I1.P1").WithLocation(6, 9)); break; @@ -3472,7 +3472,7 @@ class Test1 : I1 else { compilation1.VerifyDiagnostics( - // (6,9): warning CS9265: The 'get' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // (6,9): warning CS9265: The 'get' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // get Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I1.P1").WithLocation(6, 9)); } @@ -3538,7 +3538,7 @@ class Test1 : I1 break; case (true, false): compilation1.VerifyDiagnostics( - // (7,9): warning CS9265: The 'set' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // (7,9): warning CS9265: The 'set' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // set => System.Console.WriteLine("set P1"); Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I1.P1").WithLocation(7, 9)); break; @@ -3558,7 +3558,7 @@ class Test1 : I1 // (4,9): error CS0525: Interfaces cannot contain instance fields // int P1 Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9), - // (7,9): warning CS9265: The 'set' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // (7,9): warning CS9265: The 'set' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // set => System.Console.WriteLine("set P1"); Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I1.P1").WithLocation(7, 9)); break; @@ -3623,7 +3623,7 @@ class Test1 : I1 else { compilation1.VerifyDiagnostics( - // (7,9): warning CS9265: The 'set' accessor of property 'I1.P1' should use the backing 'field' because the other accessor is using it. + // (7,9): warning CS9265: The 'set' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // set => System.Console.WriteLine("set P1"); Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I1.P1").WithLocation(7, 9)); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/PartialPropertiesTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/PartialPropertiesTests.cs index d73848ca97db2..8914b12feb8f6 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/PartialPropertiesTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/PartialPropertiesTests.cs @@ -1521,7 +1521,7 @@ partial class C // (11,17): error CS8799: Both partial member declarations must have identical accessibility modifiers. // partial int P1 { private get => 1; private set; } Diagnostic(ErrorCode.ERR_PartialMemberAccessibilityDifference, "P1").WithLocation(11, 17), - // (11,30): warning CS9265: The 'get' accessor of property 'C.P1' should use the backing 'field' because the other accessor is using it. + // (11,30): warning CS9265: The 'get' accessor of property 'C.P1' should use 'field' because the other accessor is using it. // partial int P1 { private get => 1; private set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.P1").WithLocation(11, 30), // (11,30): error CS8799: Both partial member declarations must have identical accessibility modifiers. @@ -5037,10 +5037,10 @@ partial class C var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (4,32): warning CS9265: The 'get' accessor of property 'C.Prop1' should use the backing 'field' because the other accessor is using it. + // (4,32): warning CS9265: The 'get' accessor of property 'C.Prop1' should use 'field' because the other accessor is using it. // public partial int Prop1 { get => 1; set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Prop1").WithLocation(4, 32), - // (7,37): warning CS9265: The 'set' accessor of property 'C.Prop2' should use the backing 'field' because the other accessor is using it. + // (7,37): warning CS9265: The 'set' accessor of property 'C.Prop2' should use 'field' because the other accessor is using it. // public partial int Prop2 { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.Prop2").WithLocation(7, 37)); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index b406f9a201083..f16cd4863ec3f 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -8141,10 +8141,10 @@ public void CS0501ERR_ConcreteMissingBody02() Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("C.R.get").WithLocation(5, 30)); CreateCompilation(text).VerifyDiagnostics( - // (3,25): warning CS9265: The 'set' accessor of property 'C.P' should use the backing 'field' because the other accessor is using it. + // (3,25): warning CS9265: The 'set' accessor of property 'C.P' should use 'field' because the other accessor is using it. // public int P { get; set { } } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.P").WithLocation(3, 25), - // (4,20): warning CS9265: The 'get' accessor of property 'C.Q' should use the backing 'field' because the other accessor is using it. + // (4,20): warning CS9265: The 'get' accessor of property 'C.Q' should use 'field' because the other accessor is using it. // public int Q { get { return 0; } set; } Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Q").WithLocation(4, 20), // (5,30): warning CS0626: Method, operator, or accessor 'C.R.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. From 41ccabc826a1d1f6cfbd560dad8a31d66492f333 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 14 Oct 2024 16:31:39 -0700 Subject: [PATCH 6/7] Inline local function and adjust formatting --- .../Source/SourcePropertySymbolBase.cs | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs index ba33220db5222..2b611cea14e60 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs @@ -313,42 +313,43 @@ protected void CheckInitializerIfNeeded(BindingDiagnosticBag diagnostics) } #nullable enable - private void CheckFieldKeywordUsage(BindingDiagnosticBag diagnostics) + private static void CheckFieldKeywordUsage(SourcePropertySymbolBase property, BindingDiagnosticBag diagnostics) { - if (!this.DeclaringCompilation.IsFeatureEnabled(MessageID.IDS_FeatureFieldKeyword)) + Debug.Assert(property.PartialImplementationPart is null); + if (!property.DeclaringCompilation.IsFeatureEnabled(MessageID.IDS_FeatureFieldKeyword)) { return; } - check((SourcePropertySymbolBase?)PartialImplementationPart ?? this, diagnostics); - - static void check(SourcePropertySymbolBase @this, BindingDiagnosticBag diagnostics) + SourcePropertyAccessorSymbol? accessorToBlame = null; + var propertyFlags = property._propertyFlags; + var getterUsesFieldKeyword = (propertyFlags & Flags.GetterUsesFieldKeyword) != 0; + var setterUsesFieldKeyword = (propertyFlags & Flags.SetterUsesFieldKeyword) != 0; + if (property._setMethod is { IsAutoPropertyAccessor: false } setMethod + && !setterUsesFieldKeyword + && !property.IsSetOnEitherPart(Flags.HasInitializer) + && (property.HasAutoPropertyGet || getterUsesFieldKeyword)) { - SourcePropertyAccessorSymbol? accessorToBlame = null; - var propertyFlags = @this._propertyFlags; - var getterUsesFieldKeyword = (propertyFlags & Flags.GetterUsesFieldKeyword) != 0; - var setterUsesFieldKeyword = (propertyFlags & Flags.SetterUsesFieldKeyword) != 0; - if (@this._setMethod is { IsAutoPropertyAccessor: false } setMethod && !setterUsesFieldKeyword && !@this.IsSetOnEitherPart(Flags.HasInitializer) && (@this.HasAutoPropertyGet || getterUsesFieldKeyword)) - { - accessorToBlame = setMethod; - } - else if (@this._getMethod is { IsAutoPropertyAccessor: false } getMethod && !getterUsesFieldKeyword && (@this.HasAutoPropertySet || setterUsesFieldKeyword)) - { - accessorToBlame = getMethod; - } + accessorToBlame = setMethod; + } + else if (property._getMethod is { IsAutoPropertyAccessor: false } getMethod + && !getterUsesFieldKeyword + && (property.HasAutoPropertySet || setterUsesFieldKeyword)) + { + accessorToBlame = getMethod; + } - if (accessorToBlame is not null) + if (accessorToBlame is not null) + { + var accessorName = accessorToBlame switch { - var accessorName = accessorToBlame switch - { - { MethodKind: MethodKind.PropertyGet, IsInitOnly: false } => SyntaxFacts.GetText(SyntaxKind.GetKeyword), - { MethodKind: MethodKind.PropertySet, IsInitOnly: false } => SyntaxFacts.GetText(SyntaxKind.SetKeyword), - { MethodKind: MethodKind.PropertySet, IsInitOnly: true } => SyntaxFacts.GetText(SyntaxKind.InitKeyword), - _ => throw ExceptionUtilities.UnexpectedValue(accessorToBlame) - }; + { MethodKind: MethodKind.PropertyGet, IsInitOnly: false } => SyntaxFacts.GetText(SyntaxKind.GetKeyword), + { MethodKind: MethodKind.PropertySet, IsInitOnly: false } => SyntaxFacts.GetText(SyntaxKind.SetKeyword), + { MethodKind: MethodKind.PropertySet, IsInitOnly: true } => SyntaxFacts.GetText(SyntaxKind.InitKeyword), + _ => throw ExceptionUtilities.UnexpectedValue(accessorToBlame) + }; - diagnostics.Add(ErrorCode.WRN_AccessorDoesNotUseBackingField, accessorToBlame.GetFirstLocation(), accessorName, @this); - } + diagnostics.Add(ErrorCode.WRN_AccessorDoesNotUseBackingField, accessorToBlame.GetFirstLocation(), accessorName, property); } } #nullable disable @@ -859,7 +860,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, this.CheckModifiers(isExplicitInterfaceImplementation, Location, IsIndexer, diagnostics); CheckInitializerIfNeeded(diagnostics); - CheckFieldKeywordUsage(diagnostics); + CheckFieldKeywordUsage((SourcePropertySymbolBase?)PartialImplementationPart ?? this, diagnostics); if (RefKind != RefKind.None && IsRequired) { From b81794a4af062f88f39f3472356d4818bdc60ca1 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 14 Oct 2024 20:35:32 -0700 Subject: [PATCH 7/7] Update tests --- .../CSharp/Test/Emit3/Attributes/AttributeTests.cs | 3 --- .../Test/Emit3/Attributes/AttributeTests_Locations.cs | 6 ------ src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs | 5 ++++- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs index c9788e5f0511f..620867a4028d8 100644 --- a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests.cs @@ -2396,9 +2396,6 @@ public class Test // (6,21): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. // public int P { [field: A] get => throw null; set => throw null; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, return").WithLocation(6, 21), - // (6,50): warning CS9266: The 'set' accessor of property 'Test.P' should use 'field' because the other accessor is using it. - // public int P { [field: A] get => throw null; set => throw null; } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "Test.P").WithLocation(6, 50), // (7,22): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. // public int P2 { [field: A] get; set; } Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, return").WithLocation(7, 22), diff --git a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs index 6f309a1d3b3f1..b683ee07c9218 100644 --- a/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs +++ b/src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs @@ -632,9 +632,6 @@ int Goo } "; CreateCompilation(source).VerifyDiagnostics( - // (25,9): warning CS9266: The 'set' accessor of property 'C.Goo' should use 'field' because the other accessor is using it. - // set { } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "C.Goo").WithLocation(25, 9), // (12,10): warning CS0657: 'assembly' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, return'. All attributes in this block will be ignored. // [assembly: A] Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "assembly").WithArguments("assembly", "method, return").WithLocation(12, 10), @@ -696,9 +693,6 @@ int Goo } "; CreateCompilation(source).VerifyDiagnostics( - // (11,9): warning CS9266: The 'get' accessor of property 'C.Goo' should use 'field' because the other accessor is using it. - // get { return 0; } - Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "C.Goo").WithLocation(11, 9), // (14,10): warning CS0657: 'assembly' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. // [assembly: A] Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "assembly").WithArguments("assembly", "method, param, return").WithLocation(14, 10), diff --git a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs index 5194329f4a286..dfa456b2337a9 100644 --- a/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs @@ -1415,7 +1415,10 @@ static void ReportMember(MemberInfo member) Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, return").WithLocation(22, 25), // (23,54): warning CS0657: 'field' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'method, param, return'. All attributes in this block will be ignored. // public static object Q5 { get { return field; } [field: A(5)] set { } } - Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, param, return").WithLocation(23, 54)); + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "field").WithArguments("field", "method, param, return").WithLocation(23, 54), + // (23,67): warning CS9266: The 'set' accessor of property 'B.Q5' should use 'field' because the other accessor is using it. + // public static object Q5 { get { return field; } [field: A(5)] set { } } + Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "B.Q5").WithLocation(23, 67)); CompileAndVerify(comp, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(""" B.P1: A(0),