Skip to content

Improve diagnostics for generics in enum case #69055

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

Closed
wants to merge 9 commits into from

Conversation

dancamarotto
Copy link
Contributor

This PR enhances the error description when declaring generics in enum cases, making it more informative and helpful for developers encountering such issues:
generic-error-enum

Resolves #69036

auto genericParams = maybeParseGenericParams()
.getPtrOrNull();
if (genericParams) {
auto param = genericParams->getParams().front()->getStartLoc();
Copy link
Contributor

Choose a reason for hiding this comment

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

Just because we parsed a generic parameter clause doesn’t mean it’s non-empty. Please check for that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added validation for that check.

Copy link
Contributor

Choose a reason for hiding this comment

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

With this change, could case bar<>(param: Int) pass through without any diagnostics? I think this should trap as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

case bar<>(param: Int) presents the message: error: expected an identifier to name generic parameter

Copy link
Contributor

Choose a reason for hiding this comment

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

This diagnostic may be a little misleading as solving that error by adding a generic parameter name results in another error saying that generic parameters are not allowed.

I think we could do better by emitting the same generic parameter not allowed in such case as well. Any <(and or >) tokens preceding the case identifier would fall under this.

if (param) {
diagnose(param, diag::generic_param_cant_be_used_in_enum_case_decl);
Status.setIsParseError();
return Status;
Copy link
Contributor

Choose a reason for hiding this comment

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

I don’t think we need to stop parsing here

Copy link
Contributor Author

@dancamarotto dancamarotto Oct 9, 2023

Choose a reason for hiding this comment

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

removed the return and moved the validation to be executed before checking for params.

Also added a few more tests to cover this.

@@ -636,3 +636,9 @@ if case nil = foo1 {} // Okay
if case .none? = foo1 {} // Okay
if case nil = foo2 {} // Okay
if case .none?? = foo2 {} // Okay

enum EnumCaseWithGenericDeclaration {
case foo<T>(T) // expected-error {{generic signature cannot be declared in enum 'case'. did you mean to attach it to enum declaration?}}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we offer the second clause here as a fixit that reparents the generic parameters into the parent enum declaration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We probably can, I just have no idea how to implement this change however - will take a better look to see if I can come up with something.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -8980,6 +8980,18 @@ Parser::parseDeclEnumCase(ParseDeclOptions Flags,
if (ArgParams.isNull() || ArgParams.hasCodeCompletion())
return ParserStatus(ArgParams);
}

// See if there are generic params.
auto genericParams = maybeParseGenericParams()
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please add tests for invalid generic clause like

case someCase<Partial
case someOtherCase<subscript>(param: subscript)

It seems like maybeParseGenericParams may emit other diagnostics when the generic parmeters is invalid, which will be removed entirely when the generic clause is gone anyways.

Comment on lines 8991 to 8993
// check if there's a following argument type after
// generic declaration and parse it to ignore it.
if (Tok.isFollowingLParen()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Because this diagnosis falls through without returning, you can move this generic result check to be done prior to the previous if statement (which parses the argument type)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good suggestion. done.

@bnbarham
Copy link
Contributor

bnbarham commented Oct 9, 2023

Looks like this is a similar case in the new Swift parser (in swift-syntax), which we're moving towards being the only parser. Would you be interested in improving the diagnostic there as well?

@dancamarotto
Copy link
Contributor Author

dancamarotto commented Oct 9, 2023

Would you be interested in improving the diagnostic there as well?

@bnbarham sure, could you provide more info though? should these changes be made within this PR?

@bnbarham
Copy link
Contributor

bnbarham commented Oct 9, 2023

should these changes be made within this PR?

No, the new parser is implemented in apple/swift-syntax. Here's some relevant documentation for improving diagnostics in swift-syntax: https://swiftpackageindex.com/apple/swift-syntax/main/documentation/swiftparser/fixingbugs#Unhelpful-Diagnostic-Produced

@dancamarotto
Copy link
Contributor Author

the new parser is implemented in apple/swift-syntax.

I've found the related issue. Will have a look and also at the documentation you sent - thanks!

@dancamarotto
Copy link
Contributor Author

@CodaFi I've managed to implement the fixItInsert to add the generic params into the enum declaration - Also included fixItReplace for cases where the enum already contains a generic declaration.

PR is ready for re-review.

@dancamarotto dancamarotto deleted the 69036-generics-enum branch October 18, 2024 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bad diagnostic for generic parameter list on enum case
4 participants