-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
[semi-auto-props]: Require overriding all accessors #61114
Conversation
if ((!HasSetAccessor && !this.IsReadOnly) || | ||
(!HasGetAccessor && !this.IsWriteOnly)) | ||
{ | ||
diagnostics.Add(ErrorCode.ERR_AutoPropertyMustOverrideSet, Location, this); |
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.
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?
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.
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.
src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
Outdated
Show resolved
Hide resolved
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.
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) |
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.
@@ -87,6 +80,63 @@ private void VerifyTypeIL(CSharpCompilation compilation, string typeName, string | |||
CompileAndVerify(compilation).VerifyTypeIL(typeName, expected); | |||
} | |||
|
|||
[Fact] | |||
public void TestVirtualPropertyOverride() |
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.
@@ -87,6 +80,63 @@ private void VerifyTypeIL(CSharpCompilation compilation, string typeName, string | |||
CompileAndVerify(compilation).VerifyTypeIL(typeName, expected); | |||
} | |||
|
|||
[Fact] | |||
public void TestVirtualPropertyOverride() |
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.
if ((!HasSetAccessor && !this.IsReadOnly) || | ||
(!HasGetAccessor && !this.IsWriteOnly)) | ||
{ | ||
diagnostics.Add(ErrorCode.ERR_AutoPropertyMustOverrideSet, Location, this); |
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.
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
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.
Indeed. Calling GetFieldsToEmit
before anything does a force binding and loses the diagnostics.
Dropping diagnostics reported by 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) || |
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.
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.
@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 |
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.
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.
This is an outdated PROTOTYPE comment. I had it written when I wrote the test but before fixing implementation. Removing.
Done with review pass (commit 1). |
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
Outdated
Show resolved
Hide resolved
Done with review pass (commit 7) |
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.
Implementation looks good. One test comment.
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
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.
LGTM (commit 9)
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.
LGTM (commit 9)
Test plan: #57012
LDM notes: https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-05-02.md#partial-overrides-of-virtual-properties
@AlekseyTs @333fred