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.
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.
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.
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.
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.
Please update the specification so this code can be checked against that.
In reply to: 436051230 [](ancestors = 436051230,436049242)
RikkiGibson
left a comment
There was a problem hiding this comment.
LGTM with some minor comments/questions.
| // 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.
should the above SortKey positions be adjusted? #Resolved
There was a problem hiding this comment.
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.
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.
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.
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
| // record C(dynamic X) : Base(X) | ||
| Diagnostic(ErrorCode.ERR_NoDynamicPhantomOnBaseCtor, "(X)").WithLocation(11, 27) | ||
| ); | ||
| } |
There was a problem hiding this comment.
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.
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 |
|
|
||
| public override void VisitRecordDeclaration(RecordDeclarationSyntax node) | ||
| { | ||
| Debug.Assert(((RecordDeclarationSyntax)node).ParameterList is object); |
There was a problem hiding this comment.
RecordDeclarationSyntax [](start = 27, length = 23)
nit: redundant cast #Resolved
|
|
||
| bool isBaseConstructorInitializer = initializerArgumentListOpt == null || | ||
| initializerArgumentListOpt.Parent.Kind() == SyntaxKind.BaseConstructorInitializer; | ||
| initializerArgumentListOpt.Parent.Kind() != SyntaxKind.ThisConstructorInitializer; |
There was a problem hiding this comment.
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.
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)
|
@AlekseyTs I'm testing on top of this PR, and encountered an unexpected error: Can you add a test like this? #Resolved |
agocke
left a comment
There was a problem hiding this comment.
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.
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.
I assume the following is legal:
Yes, this works, adding test in the next PR
In reply to: 436186239 [](ancestors = 436186239)
|
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) |
jcouv
left a comment
There was a problem hiding this comment.
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