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

Exhaustivity warnings on nested case classes #13030

Merged
merged 1 commit into from
Jul 12, 2021

Conversation

dwijnand
Copy link
Member

@dwijnand dwijnand commented Jul 8, 2021

Fixes #13003, by refixing #12485 (PR #12488).

Part of the issue is that isCheckable behaves differently under
-Ycheck-all-patmat and our tests only run under that flag. So for
starters I added a test variant where that flag isn't used. I'd like to
understand why that flag exists to see if we could remove it from
guarding the logic and the tests.

@bishabosha
Copy link
Member

test performance please

@dottybot
Copy link
Member

dottybot commented Jul 8, 2021

performance test scheduled: 1 job(s) in queue, 1 running.

@dottybot
Copy link
Member

dottybot commented Jul 8, 2021

Performance test finished successfully:

Visit https://dotty-bench.epfl.ch/13030/ to see the changes.

Benchmarks is based on merging with master (110e5cb)

Copy link
Contributor

@liufengyun liufengyun left a comment

Choose a reason for hiding this comment

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

LGTM, thank you @dwijnand 👍

classSym.isAllOf(JavaEnumTrait)
classSym.isAllOf(JavaEnumTrait) ||
classSym.is(Case) && productSelectorTypes(tpw, sel.srcPos).exists(isCheckable(_))
})
Copy link
Contributor

Choose a reason for hiding this comment

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

I tried to understand why the cache breaks the cycle but couldn't figure it out --- when the recursive call tries to use the cache, the value is not there yet, so it will run into cycles.

But obviously, it works. Could you give a hint? 😄

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 had exactly the same thought after I sent the PR and didn't understand it either.

But I think I do now: because the test case for #12488 is running under -Ycheck-all-patmat so it's short-circuting... Damn -Ycheck-all-patmat. Why does that flag exist? It's misleading test results, as I see it.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's created a long time ago for testing whether the algorithm works generally. Now it becomes a "feature".

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 only partially understood your answer there. Do you think it should continue to exist? In Scala 2 the only equivalents we have are: -Xlint:strict-unsealed-patmat to consider unsealed scrutinees checkable and -Xnon-strict-patmat-analysis to disable the pessimistic approximation of guards and custom extractors not matching (the "strict" patmat analysis).

Perhaps looking to transition the tests and the logic out from under the -Ycheck-all-patmat would be a good project to get me pinging around the patmat code, learning parts of it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you think it should continue to exist?

I don't really have an opinion here. It's not supposed to be used by end-users. So there is room to change.

@dwijnand dwijnand marked this pull request as draft July 8, 2021 16:47
Fixes scala#13003, by refixing scala#12485 (PR scala#12488).

Part of the issue is that isCheckable behaves differently under
-Ycheck-all-patmat and our tests only run under that flag.  So for
starters I added a test variant where that flag isn't used.  I'd like to
understand why that flag exists to see if we could remove it from
guarding the logic and the tests.

Also make sure that any patmat test that throws an exception fails the
test...
@dwijnand dwijnand force-pushed the exhaust-case-class-in-case-class branch from d8c4ad8 to 9fd4000 Compare July 9, 2021 14:29
@dwijnand dwijnand marked this pull request as ready for review July 9, 2021 15:52
@dwijnand dwijnand requested a review from liufengyun July 9, 2021 15:53
classSym.isAllOf(JavaEnumTrait) ||
classSym.is(Case) && {
if seen.add(tpw) then productSelectorTypes(tpw, sel.srcPos).exists(isCheckable(_))
else true // recursive case class: return true and other members can still fail the check
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems false aligns better with the protocol that if a component is sealed, then perform the check.

Copy link
Member Author

Choose a reason for hiding this comment

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

Given something like case class Foo(parent: Option[Foo], other: Bar) this else branch is hit when we've running isCheckable(Foo) on the Foo in the Option. My thinking is we can optimistically return true here, and then whether or not Bar is checkable will determine if the top Foo is checkable. So I think true is right here, no?

Copy link
Contributor

Choose a reason for hiding this comment

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

Given the following type:

case class A(a: A)

IIRC, the implementation above will have isCheckable(A) == true. If that's as expected, then true is fine. Otherwise, it seems false should be used here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I'm happy with that result.

@dwijnand dwijnand merged commit 9d33bb1 into scala:master Jul 12, 2021
@dwijnand dwijnand deleted the exhaust-case-class-in-case-class branch July 12, 2021 09:02
@dwijnand dwijnand added this to the 3.0.2-RC1 milestone Jul 12, 2021
@Kordyjan Kordyjan modified the milestones: 3.0.2-RC1, 3.0.2 Aug 2, 2023
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.

Missing exhaustivity when pattern matching on nested case classes
5 participants