Skip to content
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

Merged
merged 11 commits into from
Oct 16, 2024

Conversation

RikkiGibson
Copy link
Contributor

@RikkiGibson RikkiGibson commented Oct 1, 2024

#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.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Oct 1, 2024
@RikkiGibson RikkiGibson marked this pull request as ready for review October 2, 2024 02:02
@RikkiGibson RikkiGibson requested a review from a team as a code owner October 2, 2024 02:02
@RikkiGibson RikkiGibson marked this pull request as draft October 2, 2024 17:27
@RikkiGibson RikkiGibson marked this pull request as ready for review October 9, 2024 20:24
@RikkiGibson
Copy link
Contributor Author

@cston @333fred for review

@cston
Copy link
Member

cston commented Oct 9, 2024

                public string Prop { get; set => throw null!; } // 1

Minor: The ! in this test shouldn't be necessary.


Refers to: src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs:347 in b6903fd. [](commit_id = b6903fd, deletion_comment = False)

@cston
Copy link
Member

cston commented Oct 9, 2024

                partial object P1

Consider testing declarations appearing after implementations as well, in this test and the next test. (See existing PartialProperty_* tests that use bool reverseOrder.)


Refers to: src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs:264 in b6903fd. [](commit_id = b6903fd, deletion_comment = False)

@cston
Copy link
Member

cston commented Oct 9, 2024

            //     public string Prop { get; set => throw null!; } // 1

The warning for this case seems unfortunate.


Refers to: src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs:363 in b6903fd. [](commit_id = b6903fd, deletion_comment = False)

@cston

This comment was marked as resolved.

return;
}

check((SourcePropertySymbolBase?)PartialImplementationPart ?? this, diagnostics);
Copy link
Member

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>
Copy link
Member

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'?

@RikkiGibson
Copy link
Contributor Author

RikkiGibson commented Oct 10, 2024

            //     public string Prop { get; set => throw null!; } // 1

The warning for this case seems unfortunate.

Refers to: src/Compilers/CSharp/Test/Emit3/FieldKeywordTests.cs:363 in b6903fd. [](commit_id = b6903fd, deletion_comment = False)

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 string Prop { get => field ??= Compute(); set => throw null!; }. In this case an initializer actually needs to be added to silence the warning, which the diagnostic message isn't clear about currently.

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.

@jnm2
Copy link
Contributor

jnm2 commented Oct 10, 2024

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.

@RikkiGibson RikkiGibson requested a review from a team as a code owner October 14, 2024 16:55
@cston
Copy link
Member

cston commented Oct 15, 2024

It looks like the CI build failures are due to the fix in #75461.

@RikkiGibson
Copy link
Contributor Author

Have addressed feedback, merged in main, and updated more test baselines.

@RikkiGibson RikkiGibson merged commit 69b7f75 into dotnet:main Oct 16, 2024
24 checks passed
@RikkiGibson RikkiGibson deleted the field-keyword-unused-warning branch October 16, 2024 16:54
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Oct 16, 2024
@akhera99 akhera99 modified the milestones: Next, 17.13 P1 Oct 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants