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

[semi-auto-props]: Require overriding all accessors #61114

Merged

Conversation

Youssef1313
Copy link
Member

@Youssef1313 Youssef1313 commented May 3, 2022

@Youssef1313 Youssef1313 requested a review from a team as a code owner May 3, 2022 21:59
@ghost ghost added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label May 3, 2022
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers and removed Community The pull request was submitted by a contributor who is not a Microsoft employee. labels May 3, 2022
if ((!HasSetAccessor && !this.IsReadOnly) ||
(!HasGetAccessor && !this.IsWriteOnly))
{
diagnostics.Add(ErrorCode.ERR_AutoPropertyMustOverrideSet, Location, this);
Copy link
Member Author

@Youssef1313 Youssef1313 May 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some questions here:

  • The actual message doesn't have anything to do with "setters", so the naming of the ErrorCode is misleading. I can rename that, should I go for it (it's already misleading prior to my change)?
  • The actual message is Auto-implemented properties must override all accessors of the overridden property., is it already accurate? I don't know what will be the expecting "branding" of semi-auto properties? Should we mention them as "Auto-implemented properties" in error messages, or as "Semi-auto implemented properties", or something else?
  • I'm adding the diagnostic just after we create the backing field to avoid accessing FieldKeywordBackingField early which will trigger extra binding. Is that a good/correct way?

Copy link
Contributor

@AlekseyTs AlekseyTs May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual message doesn't have anything to do with "setters", so the naming of the ErrorCode is misleading. I can rename that, should I go for it (it's already misleading prior to my change)?

We prefer pure refactoring changes (a rename is a pure refactoring) kept separate from behavior changes.

The actual message is "Auto-implemented properties must override all accessors of the overridden property.", is it already accurate? I don't know what will be the expecting "branding" of semi-auto properties? Should we mention them as "Auto-implemented properties" in error messages, or as "Semi-auto implemented properties", or something else?

Consider adding a dedicated (new) error. Something like: "Properties using 'field' keyword must override all accessors of the overridden property."

I'm adding the diagnostic just after we create the backing field to avoid accessing FieldKeywordBackingField early which will trigger extra binding. Is that a good/correct way?

I think other comments already provided feedback on the implementation strategy.

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done review pass (commit 1). Did not look at tests.

@@ -194,10 +194,10 @@ internal virtual ImmutableArray<LocalFunctionSymbol> GetDeclaredLocalFunctionsFo
return this.Next.GetDeclaredLocalFunctionsForScope(scopeDesignator);
}

internal virtual FieldSymbol? GetSymbolForPossibleFieldKeyword()
internal virtual FieldSymbol? GetSymbolForPossibleFieldKeyword(BindingDiagnosticBag diagnostics)
Copy link
Contributor

@AlekseyTs AlekseyTs May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BindingDiagnosticBag diagnostics

I extremely dislike the idea of bundling any diadnostic reporting with this API. I think there was already an attempt to do this in another PR. #Closed

@@ -87,6 +80,63 @@ private void VerifyTypeIL(CSharpCompilation compilation, string typeName, string
CompileAndVerify(compilation).VerifyTypeIL(typeName, expected);
}

[Fact]
public void TestVirtualPropertyOverride()
Copy link
Contributor

@AlekseyTs AlekseyTs May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestVirtualPropertyOverride

I do not see a single scenario with multiple field keywords used by the same property. #Closed

@@ -87,6 +80,63 @@ private void VerifyTypeIL(CSharpCompilation compilation, string typeName, string
CompileAndVerify(compilation).VerifyTypeIL(typeName, expected);
}

[Fact]
public void TestVirtualPropertyOverride()
Copy link
Contributor

@AlekseyTs AlekseyTs May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestVirtualPropertyOverride

Please add a test where SemanticModel is the first one to bind the accessor. Are we going to get any diagnostics after that? #Closed

if ((!HasSetAccessor && !this.IsReadOnly) ||
(!HasGetAccessor && !this.IsWriteOnly))
{
diagnostics.Add(ErrorCode.ERR_AutoPropertyMustOverrideSet, Location, this);
Copy link
Contributor

@AlekseyTs AlekseyTs May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

diagnostics.Add(ErrorCode.ERR_AutoPropertyMustOverrideSet, Location, this);

Reporting any diagnostics here conditionally, based on whether the symbol is created now or by another call, is really a bad idea. The caller of this API is method binding, it is not responsible to propagate this diagnostics to a "user". The diagnostics can be discarded. In fact, EnsureBackingFieldIsSynthesized below does exactly that. Whether an error is reported to a user shouldn't depend on the order of operations performed by compiler internally. I think it should be pretty easy to come up with a test scenario, for which this error is simply getting "dropped on the floor". Please create a test like that before making changes to the current implementation. #Closed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Calling GetFieldsToEmit before anything does a force binding and loses the diagnostics.

@AlekseyTs
Copy link
Contributor

AlekseyTs commented May 4, 2022

                binder?.BindMethodBody(getMethod.SyntaxNode, BindingDiagnosticBag.Discarded);

Dropping diagnostics reported by GetOrCreateBackingField?


In reply to: 1117364955


Refers to: src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs:448 in 712aa77. [](commit_id = 712aa77, deletion_comment = False)

isCreatedForFieldKeyword)
{
// semi auto property should override all accessors.
if ((!HasSetAccessor && !this.IsReadOnly) ||
Copy link
Contributor

@AlekseyTs AlekseyTs May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

((!HasSetAccessor && !this.IsReadOnly) ||

Please add an explicit check for IsOverrides #Closed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlekseyTs Yup I was going to do that. I added the IsOverride assert in another PR just to be sure my assumption is correct :)

comp.TestOnlyCompilationData = accessorBindingData;
comp.VerifyDiagnostics(
// (10,25): error CS8080: Auto-implemented properties must override all accessors of the overridden property.
// public override int P1 { get => field; } // PROTOTYPE(semi-auto-props): This should error
Copy link
Contributor

@AlekseyTs AlekseyTs May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// PROTOTYPE(semi-auto-props): This should error

For this and other similar comments, please, clarify what exact error do you expect to report in the future. #Closed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an outdated PROTOTYPE comment. I had it written when I wrote the test but before fixing implementation. Removing.

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 1).

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 7)

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation looks good. One test comment.

@Youssef1313 Youssef1313 requested review from AlekseyTs and 333fred May 6, 2022 06:00
Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (commit 9)

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (commit 9)

@AlekseyTs AlekseyTs merged commit f214736 into dotnet:features/semi-auto-props May 9, 2022
@Youssef1313 Youssef1313 deleted the semi-override-all branch May 12, 2022 04:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants