Skip to content

Implement parsing for record_base_arguments.#44733

Merged
AlekseyTs merged 4 commits intodotnet:features/recordsfrom
AlekseyTs:Records_01
Jun 2, 2020
Merged

Implement parsing for record_base_arguments.#44733
AlekseyTs merged 4 commits intodotnet:features/recordsfrom
AlekseyTs:Records_01

Conversation

@AlekseyTs
Copy link
Contributor

record_class_base
    : class_type record_base_arguments?
    | interface_type_list
    | class_type record_base_arguments? ',' interface_type_list
    ;

record_base_arguments
    : '(' argument_list? ')'
    ;

```
record_class_base
    : class_type record_base_arguments?
    | interface_type_list
    | class_type record_base_arguments? ',' interface_type_list
    ;

record_base_arguments
    : '(' argument_list? ')'
    ;
```
@AlekseyTs AlekseyTs requested review from agocke, cston and jcouv May 31, 2020 02:59
@AlekseyTs AlekseyTs requested a review from a team as a code owner May 31, 2020 02:59
}

private BaseListSyntax ParseBaseList()
private BaseListSyntax ParseBaseList(SyntaxToken classOrStructOrInterfaceKeyword, bool haveParameters)
Copy link
Member

@gafter gafter May 31, 2020

Choose a reason for hiding this comment

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

ParseBaseList [](start = 31, length = 13)

This syntax contradicts the records specification at https://github.com/dotnet/csharplang/blob/master/proposals/records.md. According to the records specification, a class declaration with parameters has no base clause. The grammar appearing in the OP is not used in any production so it does not affect the specification.

If records are permitted to have base clauses and/or base ctor arguments, please document those (syntax, static semantics, and dynamic semantics) in https://github.com/dotnet/csharplang/blob/master/proposals/records.md so this PR can be reviewed against the specification. If a record class is permitted to have a base type, please adjust the other sections of the specification to account for that. #Resolved

Copy link
Contributor Author

@AlekseyTs AlekseyTs Jun 1, 2020

Choose a reason for hiding this comment

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

The syntax is specified in docs\features\records.md and the desired effect of the PR is clearly stated in the description. I think this is good enough to be able to review the PR based on that. Clearly the definition of static semantics, and dynamic semantics is not necessary because this PR isn't trying to implement these aspects of the feature. CC @agocke.


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

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.

The document https://github.com/dotnet/roslyn/blob/master/docs/features/records.md is the same four-year-old draft that was moved to the rejected folder in csharplang recently. Language specifications are kept in csharplang. The current specification for records is at https://github.com/dotnet/csharplang/blob/master/proposals/records.md and there is clearly no base clause in the syntax. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The document https://github.com/dotnet/csharplang/blob/master/proposals/covariant-returns.md is the same one that was moved to the rejected folder in csharplang recently. Language specifications are kept in csharplang.

I am not sure what point you are trying to make and how covariant-returns.md is related to this PR. The document I referenced above is https://github.com/dotnet/roslyn/blob/features/records/docs/features/records.md

The current specification for records is at https://github.com/dotnet/csharplang/blob/master/proposals/records.md and there is clearly no base clause in the syntax.

I understand that. I believe the PR description is sufficient to draw conclusion about the intent. Could you review this PR assuming that this is the design? Is it not clear? If you have questions on the grammar, I might be able to answer them. If you have arguments against the proposed grammar, this should be taken offline and should not block this PR. We will get necessary approvals and reconcile the specification separately. Otherwise, you always have an option to not review this PR. Thanks.


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

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.

Our process is not to infer the specification from draft implementation, but to check the draft implementation against the specification. #WontFix

Copy link
Contributor Author

@AlekseyTs AlekseyTs Jun 1, 2020

Choose a reason for hiding this comment

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

Our process is not to infer the specification from draft implementation, but to check the draft implementation against the specification.

When multiple people sharing work on the feature under tight schedule, some things happen in parallel, or out of perfect alignment.


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

@AlekseyTs
Copy link
Contributor Author

@agocke, @cston, @jcouv, @dotnet/roslyn-compiler Please review.

@agocke
Copy link
Member

agocke commented Jun 1, 2020

This seems to match what I wrote up at dotnet/csharplang#3527 so it seems like we're on the same page. I'll try to review this tomorrow. #Closed

@AlekseyTs
Copy link
Contributor Author

@agocke, @cston, @jcouv, @dotnet/roslyn-compiler Please review.

@gafter
Copy link
Member

gafter commented Jun 1, 2020

This seems to match what I wrote up at dotnet/csharplang#3527 so it seems like we're on the same page.

That specification does not have an argument list in the base clause for a class, struct, or interface, which is what is implemented by this PR. #Resolved

@AlekseyTs
Copy link
Contributor Author

AlekseyTs commented Jun 1, 2020

That specification does not have an argument list in the base clause for a class, struct, or interface, which is what is implemented by this PR.

We don't have separate parsing for record types. Structures are valid record types, at least syntactically, at the moment. For structures and interfaces we parse the argument list in error recovery mode and report syntax error for it. #Resolved

@agocke
Copy link
Member

agocke commented Jun 1, 2020

I will have a PR with the change to use the record syntax shortly and we can merge those together whenever it's appropriate. #Resolved

{
argumentList = this.ParseParenthesizedArgumentList();

if (classOrStructOrInterfaceKeyword.Kind != SyntaxKind.ClassKeyword || !haveParameters)
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.

!haveParameters [](start = 91, length = 15)

The specification at dotnet/csharplang#3527 does not support an error in the case where there are no parameters. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The specification at dotnet/csharplang#3527 does not support an error in the case where there are no parameters.

As it stands right now, parameters are required for a record declaration and only a class record declaration is allowed to have arguments. Given the current implementation of type parsing, presence of parameters is an indicator that we are parsing a record. This is a error recovery situation, we could not even attempt to parse the arguments, but I chose to parse them and report an error instead. Reconciling parsing of other parts of record declaration with the updated spec is out of scope for this PR. When that work will happen, necessary adjustments are going to be made to this code, if necessary.


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

{
argumentList = this.ParseParenthesizedArgumentList();

if (classOrStructOrInterfaceKeyword.Kind != SyntaxKind.ClassKeyword || !haveParameters)
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.

ClassKeyword [](start = 75, length = 12)

The specification does not support arguments when the class keyword is used. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The specification does not support arguments when the class keyword is used.

As clearly stated in the PR title, this PR is focused on parsing base clause for records. Given current implementation, class keyword is required to declare a record. Reconciling that aspect of parsing with the updated spec is out of scope for this PR.


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

<Kind Name="SimpleBaseType"/>
<Field Name="Type" Type="TypeSyntax" Override="true">
</Field>
<Field Name="ArgumentList" Type="ArgumentListSyntax" Optional="true"/>
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.

ArgumentList [](start = 17, length = 12)

It feels like this is a case where a different node derived from BaseTypeSyntax would make more sense than adding arguments to SimpleBaseTypeSyntax #Pending

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It feels like this is a case where a different node derived from BaseTypeSyntax would make more sense than adding arguments to SimpleBaseTypeSyntax

I considered that, however I believe existing tools will be served better by not forcing them to change what types of nodes they need to handle. I'll record this as an open issue.


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

Copy link
Member

Choose a reason for hiding this comment

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

This anticipated future scenario (adding arguments in the base clause for records) is precisely the reason that BaseTypeSyntax was separated from SimpleBaseTypeSyntax in the first place.


In reply to: 433461884 [](ancestors = 433461884,433449588)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This anticipated future scenario (adding arguments in the base clause for records) is precisely the reason that BaseTypeSyntax was separated from SimpleBaseTypeSyntax in the first place.

Quite possibly true. We didn't have that many existing tools at the time. In order to avoid a possibility that many of the tools would need an adjustment to deal with the new node, I believe it is safer to not introduce a new node for preview 3. We will follow up on this design question at a later time.


In reply to: 433525828 [](ancestors = 433525828,433461884,433449588)

@AlekseyTs
Copy link
Contributor Author

@gafter I think I responded to all your feedback.

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. I updated the specification to note that an error is produced if the record type has a base argument list without a parameter list.

}

[Theory]
[CombinatorialData]
Copy link
Member

@agocke agocke Jun 2, 2020

Choose a reason for hiding this comment

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

I've never seen this trait before, this is pretty cool :) #Resolved

@AlekseyTs
Copy link
Contributor Author

@gafter, @cston, @jcouv, @dotnet/roslyn-compiler Please review, need a second sign-off.

1 similar comment
@AlekseyTs
Copy link
Contributor Author

@gafter, @cston, @jcouv, @dotnet/roslyn-compiler Please review, need a second sign-off.

[CombinatorialValues("class", "struct")] string typeKeyword,
[CombinatorialValues(true, false)] bool withParameters,
[CombinatorialValues(true, false)] bool withBaseArguments,
[CombinatorialValues(true, false)] bool withBody)
Copy link
Contributor

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

Are the [CombinatorialValues] attributes needed for bool parameters? #WontFix

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are the [CombinatorialValues] attributes needed for bool parameters?

I don't know, its presence works great.


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

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.

4 participants