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

Add error reporting for mirror synthesis #15164

Merged
merged 5 commits into from May 13, 2022
Merged

Conversation

szymon-rd
Copy link
Member

Fixes #15128
Added reporting for errors on mirror synthesis and modified the Synthesizer so adding errors for synthesis of another terms is also straightforward. Modified the error messages.

@szymon-rd szymon-rd marked this pull request as ready for review May 11, 2022 15:35
@szymon-rd szymon-rd changed the title [Draft] Add error reporting for mirror synthesis Add error reporting for mirror synthesis May 11, 2022
-- Error: tests/neg/mirror-synthesis-errors.scala:24:38 ----------------------------------------------------------------
24 |val testSubD = summon[Mirror.Of[SubD]] // error: takes more than one parameter list
| ^
|No given instance of type deriving.Mirror.Of[SubD] was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Of[SubD]: class SubD is not a sealed class
Copy link
Member

Choose a reason for hiding this comment

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

I find this one interesting - here Synthesiser.synthesizedMirror first checks the isGenericProduct test, which it fails, then it fails the isGenericSum test in synthesizedSumMirror, but the final error only says it is not a "sealed class". I think for it could be good to prefix the error message with it is not a product because <reason> and it is not a sum because class SubD is not a sealed class

Copy link
Collaborator

Choose a reason for hiding this comment

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

SubD is a case class. In that case, I would expect a message saying “class SubD is a case class but it …” explaining what was wrong with it.

On the other hand, if a type is neither a case class nor a sealed trait, then I would expect a message saying that “SubD should be either a case class or a sealed trait”.

Copy link
Member

Choose a reason for hiding this comment

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

we have a lot of more fine grained reasons why it can fail so I think its good to capture the errors from both branches

Copy link
Member Author

Choose a reason for hiding this comment

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

I made it so it collects errors from both branches. The error for synthesis for SubD is:

No given instance of type deriving.Mirror.Of[SubD] was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Of[SubD]: 
	* class SubD is not a generic sum because it is not a sealed class
	* class SubD is not a generic product because it takes more than one parameter list

I also removed the condition from synthesizedMirror, but synthesizedProductMirror makes an early exit anyway, so I think it's cleaner that way.

Copy link
Member

Choose a reason for hiding this comment

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

I think this is very nice!, one point is that orElse combinator reverses the order of the errors, I think it should keep the order they were generated in

@szymon-rd szymon-rd requested a review from bishabosha May 12, 2022 09:57
val reason = if !cls.isGenericProduct then
i"because ${cls.whyNotGenericProduct}"
else if !canAccessCtor(cls) then
i"because constructor of $cls is unnaccessible from the calling scope."
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
i"because constructor of $cls is unnaccessible from the calling scope."
i"because the constructor of $cls is inaccessible from the calling scope."

private def orElse(treeWithErrors1: TreeWithErrors, treeWithErrors2: => TreeWithErrors): TreeWithErrors = treeWithErrors1 match
case (tree, errors) if tree eq genericEmptyTree =>
val (tree2, errors2) = treeWithErrors2
(tree2, errors2 ::: errors)
Copy link
Member

Choose a reason for hiding this comment

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

currently the the final error generated will be at the front of the list, when I think each new error should go to the back

Suggested change
(tree2, errors2 ::: errors)
(tree2, errors ::: errors2)

@szymon-rd szymon-rd requested a review from bishabosha May 13, 2022 10:55
@@ -2,5 +2,5 @@
8 |val baz = summon[Mirror.Of[SubA[Int] | SubB[Int]]] // error
| ^
|No given instance of type deriving.Mirror.Of[SubA[Int] | SubB[Int]] was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Of[SubA[Int] | SubB[Int]]:
| * class Cov is not a generic sum because it is not a sealed class
| * class Cov is not a generic product
Copy link
Member

Choose a reason for hiding this comment

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

this is another interesting one, to the user seeing this error, it might not be obvious why the error mentions Cov, and not SubA or SubB, I think this can wait for a new PR but perhaps we should explain why the union collapses to its common superclass, which is why we reject it.

@bishabosha bishabosha added the release-notes Should be mentioned in the release notes label May 13, 2022
@bishabosha bishabosha added this to the 3.2.0-RC1 milestone May 13, 2022
@bishabosha
Copy link
Member

bishabosha commented May 13, 2022

@szymon-rd would you like to add a small bit in this section to show an example of the error if a mirror can't be synthesised?

@szymon-rd szymon-rd requested a review from bishabosha May 13, 2022 14:54
@szymon-rd
Copy link
Member Author

szymon-rd commented May 13, 2022

@bishabosha I added the docs section in the last commit, could you take a quick look at it?

@bishabosha
Copy link
Member

very nice stuff!

@bishabosha bishabosha enabled auto-merge May 13, 2022 14:57
@bishabosha bishabosha merged commit fd6b48f into scala:main May 13, 2022
@Kordyjan Kordyjan removed this from the 3.2.0-RC1 milestone Aug 1, 2023
@Kordyjan Kordyjan added this to the 3.2.0 milestone Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-notes Should be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

add addendum to implicit search failure for failed Mirror synthesis
4 participants