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

Use inherited properties for records #44705

Merged
merged 9 commits into from
Jun 3, 2020
Merged

Conversation

cston
Copy link
Member

@cston cston commented May 29, 2020

@cston cston requested a review from a team as a code owner May 29, 2020 23:02
@cston cston added this to the 16.7.P3 milestone May 29, 2020
@gafter gafter self-requested a review May 30, 2020 01:13
@cston
Copy link
Member Author

cston commented Jun 1, 2020

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

@gafter gafter Jun 1, 2020

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

Copy link
Member Author

@cston cston Jun 2, 2020

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

@cston cston requested review from agocke and a team June 2, 2020 19:38
{
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
Copy link
Member

@gafter gafter Jun 2, 2020

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

Copy link
Member

Choose a reason for hiding this comment

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

#44785


In reply to: 434217176 [](ancestors = 434217176)

"System.Object B.P7 { get; init; }",
};
AssertEx.Equal(expectedMembers, actualMembers);
AssertEx.Equal(new string[0], actualMembers);
Copy link
Member

@gafter gafter Jun 2, 2020

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

Copy link
Member Author

@cston cston Jun 2, 2020

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

@gafter gafter Jun 2, 2020

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

Copy link
Member Author

@cston cston Jun 2, 2020

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();
Copy link
Member

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

Copy link
Member

Choose a reason for hiding this comment

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

I assume you will work with @agocke to resolve the conflict (I expect by modifying the spec).


In reply to: 434224682 [](ancestors = 434224682)

@"abstract class A
{
public abstract int X { get; }
public virtual int Y { get; }
Copy link
Member

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.

Copy link
Member

Choose a reason for hiding this comment

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

Or do it when handling #44785


In reply to: 434231286 [](ancestors = 434231286)

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

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

:shipit:

Copy link
Member

@agocke agocke left a 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
Copy link
Member

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.

Copy link
Member Author

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

Choose a reason for hiding this comment

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

Same here.

@cston cston closed this Jun 3, 2020
@cston cston reopened this Jun 3, 2020
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