Skip to content

Change pattern matcher #2822

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 26 commits into from
Closed

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Jun 30, 2017

A rewrite of the pattern matcher. It

  • simplifies and clarifies structure (470 LOC instead of 1038)
  • keeps generated trees small and readable
  • improves debuggability since pattern matching decision trees can be pretty-printed

Based on #2820. The hardest part was actually to get #2820 right. Once that was done
it was possible to make steady progress on the pattern matcher itself.

odersky added 24 commits June 30, 2017 18:48
As the saying goes: "let erasure handle it... "

The reason for the change is that things were a mess before

 - isInstanceOfEvaluator did not handle &/| types. It would
   be hard to change that since it was looking at erased types.
 - isInstanceEvaluator, but not TypeTestCasts added null-checks
 - therefore, necessary null-checks were not emitted on some tests of
   the form `x.isInstanceOf[A & B]`.
 - the pattern matcher patched this up by inserting some null checks
   on its own, whereas it should just have let the translation of
   isInstanceOf do the job.
To be documented once we figured out whether it works.
The optimizer seems to do some optimizations regarding
simplifications of pattern matchings. This masks
errors to be reported later at erasure.

The optimizer should perform these actions only
after erasure.
 - drop a test which prevented a check in isInstanceOfEvaluator but which
   can be dropped with the more precise types in TypeTestCasts

 - move a test which was only partially effective in RefChecks to TypeTestCasts
   (problem is again testing against &/| types).
IsInstanceOfEvaluator as prone to mispredict whether
the test was generated by a pattern match or not. We fix
this by having a special type test symbol that represents
tests generated by a pattern match.
We had:

scala> null.isInstanceOf[String]
-- Warning: <console>:5:17 -----------------------------------------------------
5 |null.isInstanceOf[String]
  |^^^^^^^^^^^^^^^^^^^^^^^^^
  |this will always yield true if the scrutinee is non-null, since `Null` is a subclass of `String` (will be optimized away)
val res0: Boolean = true
scala> val x: AnyRef = null
val x: AnyRef = null
scala> x.isInstanceOf[String]
val res1: Boolean = false

Fixed by using `isNullable`.
No need to use inheritance here.
Surprisingly, this caused the IDE to crash with a MatchError.
(previous pattern matcher, not new one). I could not work out why.
But in any case it was the wrong pattern before.
This now special cases `x.isInstance[y.type]`
to `x eq y` and similarly for constant types.
Warn if a match is @switch annotated but we could
not transform code to a switch.
The new pattern matcher generates switches only for 3 or more cases.
Update bytecode tests accordingly.
 - better structure
 - better names
 - more extensive documentation
For now we keep the previous one around as PatternMatcherOld.scala
It turns out that when we restrict DropGoodCasts to
isInstanceOf tests (as opposed to pattern-matcher generated
type tests), we do not miss any error messages. Some warnings
are still be omitted under optimize, not sure whether we want
to fix that.
@odersky odersky requested a review from DarkDimius June 30, 2017 17:06
Copy link
Member

@dottybot dottybot left a comment

Choose a reason for hiding this comment

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

Hello, and thank you for opening this PR! 🎉

All contributors have signed the CLA, thank you! ❤️

Commit Messages

We want to keep history, but for that to actually be useful we have
some rules on how to format our commit messages (relevant xkcd).

Please stick to these guidelines for commit messages:

  1. Separate subject from body with a blank line
  2. When fixing an issue, start your commit message with Fix #<ISSUE-NBR>:
  3. Limit the subject line to 72 characters
  4. Capitalize the subject line
  5. Do not end the subject line with a period
  6. Use the imperative mood in the subject line ("Added" instead of "Add")
  7. Wrap the body at 80 characters
  8. Use the body to explain what and why vs. how

adapted from https://chris.beams.io/posts/git-commit

Have an awesome day! ☀️

odersky added 2 commits June 30, 2017 22:15
It seems there are more issues with local optimizations. I did not track down
details but in one case positions were wrong after a rewrite. That was tryPatternMatchError.scala.
We should track these problems down in a different PR.
@DarkDimius DarkDimius modified the milestone: 0.2 Tech Preview Jul 4, 2017
@odersky
Copy link
Contributor Author

odersky commented Jul 9, 2017

Superseded by #2829.

@odersky odersky closed this Jul 9, 2017
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.

3 participants