-
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
Use inherited properties for records #44705
Conversation
@dotnet/roslyn-compiler please review. |
public new int P1 { get; } | ||
public new int P2 { get; } | ||
} | ||
data class C(object P1, int P2, object P3, int P4) : B |
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.
object P3 [](start = 32, length = 9)
The spec has changed again. See dotnet/csharplang#3527 ... Now it appears P2
and P3
should be generated. I'll hold off reviewing more until the spec and this PR can be brought into alignment.
I'm now not sure about the correct status of this test. The spec says 'Members are synthesized unless an accessible concrete (non-abstract) member with a "matching" signature is
either inherited or declared in the record body.' but the underlying language specification doesn't define "signature" for a property. Either P4
should be synthesized (if signature includes return type) or nothing. #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.
The spec currently allows the base member to differ by signature (or member kind) if the record property would hide the base member:
Two members are considered matching if they have the same signature or would be considered "hiding" in an inheritance scenario. #ByDesign
{ | ||
}"; | ||
var comp = CreateCompilation(source); | ||
comp.VerifyDiagnostics( |
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.
VerifyDiagnostics [](start = 17, length = 17)
These diagnostics look incorrect. According to the latest spec at dotnet/csharplang#3527 'Each "matching" inherited abstract accessor is overridden' #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.
"System.Object B.P7 { get; init; }", | ||
}; | ||
AssertEx.Equal(expectedMembers, actualMembers); | ||
AssertEx.Equal(new string[0], actualMembers); |
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.
string [](start = 31, length = 6)
P5
should be synthesized per dotnet/csharplang#3527 #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.
P5
is virtual
in the base class rather than abstract
. #ByDesign
Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.X.get").WithLocation(6, 12)); | ||
// (9,12): error CS0534: 'B2' does not implement inherited abstract member 'A.X.get' | ||
// data class B2(int X, int Y) : A | ||
Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B2").WithArguments("B2", "A.X.get").WithLocation(9, 12)); |
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.
ERR_UnimplementedAbstractMethod [](start = 37, length = 31)
Error is incorrect per dotnet/csharplang#3527 #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.
Yes, we're not synthesizing overrides for abstract
properties currently. That is tracked by #44785. #Resolved
public virtual int Y { get; } | ||
}"; | ||
var comp = CreateCompilation(source); | ||
comp.VerifyDiagnostics(); |
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.
VerifyDiagnostics [](start = 17, length = 17)
This should be an error because C
contains both a declared property X
and a synthesized one, because, from dotnet/csharplang#3527
'Members are synthesized unless an accessible concrete (non-abstract) member with a "matching" signature is either inherited or declared in the record body.'
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.
@"abstract class A | ||
{ | ||
public abstract int X { get; } | ||
public virtual int Y { get; } |
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.
Please add a test like this (X
) but in which the type of the property in A
and in C
are incompatible. There should be an error that the override has the wrong type.
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.
Added #44785 (comment)
src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
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.
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 aside from comments
void addObjectEquals(MethodSymbol thisEquals) | ||
{ | ||
var objEquals = new SynthesizedRecordObjEquals(this, thisEquals); | ||
if (!memberSignatures.ContainsKey(objEquals)) | ||
{ | ||
// PROTOTYPE: Don't add if the overridden method is sealed | ||
// https://github.com/dotnet/roslyn/issues/44617: Don't add if the overridden method is sealed |
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.
I believe this behavior is correct now. The last LDM confirmed that it is an error if these methods are sealed, which I think is the current behavior.
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.
Thanks. I'll address with the Equals
changes in a separate PR.
@@ -3031,7 +3059,7 @@ void addHashCode() | |||
var hashCode = new SynthesizedRecordGetHashCode(this); | |||
if (!memberSignatures.ContainsKey(hashCode)) | |||
{ | |||
// PROTOTYPE: Don't add if the overridden method is sealed | |||
// https://github.com/dotnet/roslyn/issues/44617: Don't add if the overridden method is sealed |
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.
Same here.
Spec: https://github.com/dotnet/csharplang/blob/master/proposals/records.md
Fixes #44616
Fixes #44692