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

[SR-13039] Confusing diagnostic about protocol type not conforming to protocol #55485

Closed
typesanitizer opened this issue Jun 17, 2020 · 15 comments
Labels
compiler The Swift compiler in itself good first issue Good for newcomers improvement type checker Area → compiler: Semantic analysis

Comments

@typesanitizer
Copy link

Previous ID SR-13039
Radar rdar://problem/64517054
Original Reporter @typesanitizer
Type Improvement
Status Closed
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Improvement, StarterBug, TypeChecker
Assignee onyekachi (JIRA)
Priority Medium

md5: befe388ccc5ea473d8c09a9363e670f5

Issue Description:

For example, one might see an error like:

> Value of protocol type 'Cancellable' cannot conform to 'Cancellable'; only struct/enum/class types can conform to protocols

Hamish has written a great answer here: https://stackoverflow.com/a/43408193 .

1. We should make this diagnostic clearer (perhaps special casing when the two protocols are related), as it may not be obvious to the reader why this is not the case.
2. We should probably have an educational note for this.

@typesanitizer
Copy link
Author

@swift-ci create

@beccadax
Copy link
Contributor

A few quick notes if you’re tackling this as a starter bug:

  • The existing diagnostic is called type_cannot_conform. Searching the Swift source code for this name would be a good way to see where you’ll need to make changes.
  • docs/Diagnostics.md talks both about the style of diagnostics we usually use, and the “educational notes” feature.
  • Remember that Type has a dump() method that will print a detailed representation of the type to stderr. Calling that method near where we diagnose the existing error may help you figure out what the types will look like when you want this new diagnostic to be emitted.
  • You will probably “break” some existing tests when you change the message. This is to be expected—after all, you just changed the compiler’s behavior! Review each failing test and decide whether you meant for its behavior to change. If you did, update the test; if not, fix your code.
  • Technically, a protocol type used in this way is called an “existential”, but users don’t really understand that term (it’s a mathematical analogy). Please try not to use it in your diagnostic’s message.

@typesanitizer
Copy link
Author

Also, if something is unclear, feel free to ask a question, and feel free to @ me (varungandhi-apple) or Brent (@ brentdax) for code review on your PR.

@hborla
Copy link
Member

hborla commented Jun 23, 2020

Please tag me (@hborla) in your PR as well! And yes, please ask questions if you need help.

@swift-ci
Copy link
Collaborator

Comment by Onyekachi Ezeoke (JIRA)

theindigamer (JIRA User)
Thanks for offering to help, I am not sure I understood clearing what you meant in your first statement by providing special casing when the two protocols are related.
I have read some documentations about diagnostic and I currently want to add the educational notes first before addressing the first concern. While going through the documentation, they wasn't mentioned if they is any special naming convention for file in userdocs/diagnostics/
Is code snippet required in the educational notes. Reading up on existential protocol so as to be able to draft a note.
For the notes, I want to know if these steps is enough

  • Once I have added the markdown file in userdocs/diagnostics/

  • Associate the note with appropriate diagnostic in EducationalNotes.def

Then I can run the test, according to the documentation.
Or do I need to call NOTE(ID, Options, Text, Signature) just like we have them in DiagnosticsSema.def file ?
Sorry if my questions didn't make much sense, just trying to get the flow. Thanks.

@typesanitizer
Copy link
Author

In the general case, we will have an error like

Value of protocol type 'Q' cannot conform to 'P'; only struct/enum/class types can conform to protocols

There are two cases here:

1. When Q = P, or more generally when Q refines P.
2. All other cases.

What I meant by "perhaps special casing when the two protocols are related" was that it might make sense to have two diagnostics: one diagnostic for case 1 and a different diagnostic for case 2. Why? Case 1 is likely to be hit more frequently in practice, and we have more information available, so it would be worthwhile to have a more informative message for it. For example, if Q = P, we could say something like (strawman example)

A value of protocol type 'Q' does not conform to the protocol itself (exception: 'Error'); only concrete types such as structs, enums and classes can conform to protocols.

The educational note could also focus on the Q = P case first for simplicity and then go the the general case. This is not strictly necessary, but I think it would help understanding the specific case before the general case.

> I have read some documentations about diagnostic and I currently want to add the educational notes first before addressing the first concern.

Sure. That seems reasonable.

> While going through the documentation, they wasn't mentioned if they is any special naming convention for file in userdocs/diagnostics/

There isn't as far as I can tell. Looking at the other ones, if the title is short, then it is the title, otherwise, it is a shorter version of the title. Maybe protocol-type-non-conformance.md would be a good fit here? Or protocol-type-cannot-conform-to-protocol.md? So long as the name is somewhat descriptive, I think it should be ok. cc owenvoorhees (JIRA User)

> Is code snippet required in the educational notes.

It would be valuable to provide some code snippets showing where the error comes up. You can look at userdocs/diagnostics/associated-type-requirements.md (or the other educational notes) as an example.

I think you have the right steps for the educational note, that matches what is in docs/Diagnostics.md. You shouldn't need an extra NOTE(ID, Options, Text, Signature for this. NOTE is used for diagnostic notes which get attached to other diagnostics (usually warnings or errors) to point people to relevant parts in their own source code or provide information very concisely. You might've seen them in the Xcode UI or in the terminal marked as "note: <text>".

@swift-ci
Copy link
Collaborator

Comment by Onyekachi Ezeoke (JIRA)

theindigamer (JIRA User) Thanks so much for this wonderful explanation, you addressed all my questions very well.

@swift-ci
Copy link
Collaborator

Comment by Owen Voorhees (JIRA)

theindigamer (JIRA User) onyekachi (JIRA User) Yeah, there's no specific naming convention for the markdown files. Any name that's relatively short and uses dashes between the words is good, currently we don't display the filenames to users anywhere. Feel free to let me know if there's anything else in docs/Diagnostics.md that's unclear or would be helpful to mention!

@swift-ci
Copy link
Collaborator

Comment by Onyekachi Ezeoke (JIRA)

owenvoorhees (JIRA User) Thanks for the confirmation, I will surely let you know if I need any further clarification.

@swift-ci
Copy link
Collaborator

Comment by Onyekachi Ezeoke (JIRA)

@theblixguy Sorry I had to bring this conversation down here, I don't want to clutter the PR with too many Asks. This is as regards to your last suggestion:

I think you need two separate diagnostics here - one for a generic “does not conform” and one for self-conformance, and when protocols are related, etc and update the code so it emits one of them depending on the types.

I have looked into the code in order to know where to effect the code change, I have checked the **ERROR** macro declaration and how it was used in the DiagnosticsSema.def file, I would say I don't currently understand how all the pieces work together. Is there any form of documentation that would help me understand more how all the pieces work? Which part of the code do I modify so that it emits any of the diagnostics depending on the type? Do I have to contain the messages in one **ERROR** macro in DiagnosticsSema.def file and have the logic determine which one to emit? Sorry for asking too much, I am still pretty new here. Thanks.

@theblixguy
Copy link
Collaborator

Yeah, you can either put the message in a single ERROR diagnostic or split them into two. If you decide to use a single diagnostic, you can use %select to split the text in order to allow you to conditionally choose between them (see [this| https://github.com/apple/swift/blob/master/docs/Diagnostics.md#format-specifiers] for more info about %select).

Let’s settle on the diagnostic text/structure first and once that’s done, we can take a look at the code and tweak it (if necessary) to incorporate the new diagnostics.

@swift-ci
Copy link
Collaborator

Comment by Onyekachi Ezeoke (JIRA)

Alright, I will do that. Thanks @theblixguy.

@typesanitizer
Copy link
Author

PR link: #32524

@LucianoPAlmeida
Copy link
Collaborator

theindigamer (JIRA User) Seems PR was merged, should this be closed?

@typesanitizer
Copy link
Author

Done.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler The Swift compiler in itself good first issue Good for newcomers improvement type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

6 participants