-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add warning when property has a backing field but a manually implemented accessor does not use it #75325
Add warning when property has a backing field but a manually implemented accessor does not use it #75325
Conversation
…ted accessor does not use it
src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
Outdated
Show resolved
Hide resolved
Consider testing declarations appearing after implementations as well, in this test and the next test. (See existing Refers to: src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs:264 in b6903fd. [](commit_id = b6903fd, deletion_comment = False) |
This comment was marked as resolved.
This comment was marked as resolved.
src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Locations.cs
Outdated
Show resolved
Hide resolved
return; | ||
} | ||
|
||
check((SourcePropertySymbolBase?)PartialImplementationPart ?? this, diagnostics); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider inlining this local function.
@@ -8002,4 +8002,10 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ | |||
<data name="WRN_UninitializedNonNullableBackingField_Title" xml:space="preserve"> | |||
<value>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.</value> | |||
</data> | |||
<data name="WRN_AccessorDoesNotUseBackingField" xml:space="preserve"> | |||
<value>The '{0}' accessor of property '{1}' should use the backing 'field' because the other accessor is using it.</value> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, the backing 'field'
reads very awkwardly. Maybe just should use 'field'
?
I think this case itself, I am fine with. We can actually see that nothing is setting that field--why are you using a field? You can use a property initializer to insist that actually it is fine, if you really want. One I am less sure about is At the same time I am reluctant to abandon this syntax/declaration-based approach, and do a definite assignment pass instead a la ordinary fields, because for the getter-only case we would potentially need to analyze the constructors to know if the field is being set. |
My personal preference would be for airtightness, and the lack of earliness (having to wait for a full compilation to update the warnings) hasn't been a noticeable problem for me with existing fields and field-like events. |
It looks like the CI build failures are due to the fix in #75461. |
Have addressed feedback, merged in main, and updated more test baselines. |
#57012
The goal of this change is to catch a scenario where user is in an in-between state of using the field keyword or not. See
MigratingToFieldKeyword_
tests.This is designed to work as a basically declaration-level check. The goal was for it to be cheap and for diagnostics to appear relatively early without needing to e.g. compile the whole property and constructors, and analyze definite assignment, in order for them to appear. (i.e. a mini version of what happens at the compilation-level for ordinary fields.)
It's not meant to be airtight, but to just catch simple cases. For example, it won't complain if the keyword is used in all accessors, yet none of the uses are writing to it.
The design has a slightly odd rule as well relating to initializers. Basically, presence of an initializer removes the need for setter to use the backing field. This is because something is certainly setting the backing field if an initializer is present. This scenario was suggested by @jnm2, and we think would come up in a situation where an interface property is "read/write" but the implementation is readonly. See
MigratingToFieldKeyword_05
.