-
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
Bind base arguments fo records #44876
Conversation
@agocke, @RikkiGibson, @cston, @jcouv, @dotnet/roslyn-compiler Please review #Closed |
1 similar comment
@agocke, @RikkiGibson, @cston, @jcouv, @dotnet/roslyn-compiler Please review #Closed |
Taking a look #Resolved |
public Base() {} | ||
} | ||
|
||
record C(int X, int Y) : Base(X, Y) |
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.
Base [](start = 25, length = 4)
Please test (for semantic errors) an argument list in the base with a class
and struct
declaration (rather than a record
declaration). #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.
Please test (for semantic errors) an argument list in the base with a class and struct declaration (rather than a record declaration).
There are existing tests for parsing errors in these scenarios. However, I added some tests here as well.
In reply to: 436046885 [](ancestors = 436046885)
|
||
if (node.BaseWithArguments is SimpleBaseTypeSyntax baseWithArguments) | ||
{ | ||
VisitNodeToBind(baseWithArguments); |
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.
VisitNodeToBind [](start = 16, length = 15)
The scope rules implemented here are not supported by the specification at https://github.com/dotnet/csharplang/blob/master/proposals/records.md #WontFix
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 scope rules implemented here are not supported by the specification at https://github.com/dotnet/csharplang/blob/master/proposals/records.md
It is a well-known fact that the spec is behind. Please see https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-06-01.md
In reply to: 436049242 [](ancestors = 436049242)
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 update the specification so this code can be checked against that.
In reply to: 436051230 [](ancestors = 436051230,436049242)
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 with some minor comments/questions.
@@ -53,8 +53,7 @@ public int Position | |||
// until later when it is known if they can be optimized or not. | |||
// As a result the last emitted method tokens are synthetic ctor and then synthetic cctor (if not optimized) | |||
// Since it is not too hard, we will try keeping the same order just to be easy on metadata diffing tools and such. | |||
public static readonly LexicalSortKey SynthesizedRecordCopyCtor = new LexicalSortKey() { _treeOrdinal = int.MaxValue, _position = int.MaxValue - 3 }; | |||
public static readonly LexicalSortKey SynthesizedRecordCtor = new LexicalSortKey() { _treeOrdinal = int.MaxValue, _position = int.MaxValue - 2 }; | |||
public static readonly LexicalSortKey SynthesizedRecordCopyCtor = new LexicalSortKey() { _treeOrdinal = int.MaxValue, _position = int.MaxValue - 2 }; |
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.
should the above SortKey positions be adjusted? #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.
I've replaced this code in #44882. #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.
should the above SortKey positions be adjusted?
I am not following. Could you elaborate please?
In reply to: 436055537 [](ancestors = 436055537)
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.
For instance SynthesizedRecordObjEquals still has _position = int.MaxValue - 4
while there is no symbol with position int.MaxValue - 3
. I doubt this negatively affects anything so perhaps we can just leave it as is, especially if changing it may introduce more conflicts with other PRs. #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.
For instance SynthesizedRecordObjEquals still has _position = int.MaxValue - 4 while there is no symbol with position int.MaxValue - 3. I doubt this negatively affects anything so perhaps we can just leave it as is, especially if changing it may introduce more conflicts with other PRs.
I reverted the change in favor of in #44882.
In reply to: 436077962 [](ancestors = 436077962)
|
||
var comp = CreateCompilation(src); | ||
comp.VerifyEmitDiagnostics( | ||
// (13,16): error CS8861: Unexpected argument list. |
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.
Ideally this diagnostic would say something like "only a record with positional parameters may have a constructor initializer." We can follow up in #44826 #WontFix
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.
// record C(dynamic X) : Base(X) | ||
Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(X)").WithLocation(11, 27) | ||
); | ||
} |
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.
Do we have a test which demonstrates whether a partial record
is allowed to reiterate its base class without arguments, e.g.:
record A(int X) { }
partial record B(int X, int Y) : A(X) { }
partial record B : A { }
#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.
Do we have a test which demonstrates whether a partial record is allowed to reiterate its base class without arguments, e.g.:
I do not know. I think this is outside of scope of this PR, feel free to add a note to the Test Plan.
In reply to: 436069358 [](ancestors = 436069358)
Aleksey has suggested that if the PR receives a second sign-off that we can squash merge the PR even if he is offline at the time. #Resolved |
Looking now #Resolved |
@@ -390,6 +393,16 @@ public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax no | |||
} | |||
} | |||
|
|||
public override void VisitRecordDeclaration(RecordDeclarationSyntax node) | |||
{ | |||
Debug.Assert(((RecordDeclarationSyntax)node).ParameterList is object); |
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.
RecordDeclarationSyntax [](start = 27, length = 23)
nit: redundant cast #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.
@@ -3864,7 +3864,7 @@ private static bool IsNegativeConstantForArraySize(BoundExpression expression) | |||
NamedTypeSymbol initializerType = containingType; | |||
|
|||
bool isBaseConstructorInitializer = initializerArgumentListOpt == null || | |||
initializerArgumentListOpt.Parent.Kind() == SyntaxKind.BaseConstructorInitializer; | |||
initializerArgumentListOpt.Parent.Kind() != SyntaxKind.ThisConstructorInitializer; |
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.
nit: wouldn't it be clearer to keep the check as "parent is BaseConstructorInitializer OR parent is SimpleBaseTypeSyntax"? #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.
nit: wouldn't it be clearer to keep the check as "parent is BaseConstructorInitializer OR parent is SimpleBaseTypeSyntax"?
I think it is clearer this way, i.e. either we are dealing with "this" initializer syntax, or it is a base initializer swmantically.
In reply to: 436174617 [](ancestors = 436174617)
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 Thanks (iteration 3)
@AlekseyTs I'm testing on top of this PR, and encountered an unexpected error: Can you add a test like this? #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. Test suggestion that can be added later.
public Base() {} | ||
} | ||
|
||
partial record C(int X, int Y) : Base(X, Y) |
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 assume the following is legal:
record Base(int X);
partial record C(int X) : Base(X);
partial record C { }
Could you write a test that shows it succeeds/emits correctly? #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.
I assume the following is legal:
Yes, this works, adding test in the next PR
In reply to: 436186239 [](ancestors = 436186239)
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.
Confirmed the problem with a unittest:
|
The error is coming from generation of the copy constructor, it is not related to arguments In reply to: 639844282 [](ancestors = 639844282) |
See
In reply to: 639867910 [](ancestors = 639867910,639844282) |
Responded above, doesn't look related to the primary constructor In reply to: 639859945 [](ancestors = 639859945) |
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 Thanks (iteration 3)
From discussion with Aleksey, I'll file an issue with copy constructor (it should probably leverage copy constructor from the base, instead of no-args constructor).
Relevant LDM notes - https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-06-01.md