Skip to content

Fix #9171: Eliminate difference _ and Any in MT #9172

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 2 commits into from

Conversation

OlivierBlanvillain
Copy link
Contributor

case _ => use to be typed as a HKTypeLambda, despite not binding anything. As a result, result of match type reduction going through case _ would get further reduce that their case Any counterpart. This PR eliminates this distinction with the following changes:

  • Eliminate this distinction in typing (type case _ => as case Any =>)
  • Simplify the body of match types in non-binding cases
  • Change the match type/expression unification to treat the case _ => in a pattern like case _: Any =>

Unfortunately this change introduces a regression in matchtype-loop.scala where the loop suddenly turns into an infinite loop that doesn't stack overflow. I don't see any other way to nicely fail than to introduce a new fuel-like counter to keep track of match type reductions.

@@ -2588,7 +2588,7 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
val instances = paramInstances(new Array(caseLambda.paramNames.length), pat)
instantiateParams(instances)(body)
case _ =>
body
body.simplified
Copy link
Contributor

Choose a reason for hiding this comment

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

Why simplified here?

Copy link
Contributor Author

@OlivierBlanvillain OlivierBlanvillain Jun 15, 2020

Choose a reason for hiding this comment

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

The added test case (with case Int => instead of case _ =>) fails to compile on master with the following:

11 |  val fib2: Fib[2] = 1
   |                     ^
   |                  Found:    (1 : Int)
   |                  Required: LazyRef(Test2.Fib[(2 : Int) - (1 : Int)]) + 
   |                    LazyRef(Test2.Fib[(2 : Int) - (2 : Int)])

That's because when match type reduction simply reduces to body without going through instantiateParams reduction would stop without trying to further simplify the body in question.

@@ -6,9 +6,9 @@ object Test {
case Int => LL[LL[X]]
}
def a: L[Boolean] = ???
def b: L[Int] = ???
// def b: L[Int] = ??? // times out
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do these time out now? Isn't that a problem?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why do these time out now?

Because instead of stoping after one step of reduction we now try to keep reducing the match type body after the first step, which causes in infinite loop.

All the infinite loops that we encountered in match type reduction would eventually run out of stack, but this nicely trampolines and ultimately fails with an out of memory error.

This is indeed a problem, but the only solution I see would be to add some sort of reduction counter to match type reduction similar to -Xmax-inlines.

@nicolasstucki nicolasstucki linked an issue Jun 24, 2020 that may be closed by this pull request
`case _ =>` use to be typed as a `HKTypeLambda`, despite not binding anything.
As a result, result of match type reduction going through `case _` would get
further reduce that their `case Any` counterpart. This commit eliminates this
distinction with the following changes:

- Eliminate this distinction in typing (type `case _ =>` *as* `case Any =>`)
- Simplify the body of match types in non-binding cases
- Change the match type/expression unification to treat the `case _ =>` in a
  pattern like `case _: Any =>`

Unfortunately this change introduces a regression in `matchtype-loop.scala`
where the loop suddenly turns into an infinite loop that doesn't
stack overflow. I don't see any other way to nicely fail than to introduce a
new fuel-like counter to keep track of match type reductions.
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.

Difference between case _ and case Any in match types
2 participants