Skip to content

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.

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.

}
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