Skip to content

Fix #3561: Correctly handle switches followed by other tests in matches #3724

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

Merged
merged 6 commits into from
Jan 14, 2018

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Jan 1, 2018

No description provided.

@smarter
Copy link
Member

smarter commented Jan 1, 2018

Trying to test this I noticed that something seems very broken with @switch, we get the Could not emit switch for @switch annotated match warning in all these cases (both before and after this PR):

import scala.annotation.switch

object Test {
  def foo1(x: Int) = (x: @switch) match {
    case 1 =>
      println("a")
  }
  def foo2(x: Int) = (x: @switch) match {
    case 1 =>
      println("b")
    case 2 =>
      println("c")
  }
  def foo3(x: Int) = (x: @switch) match {
    case 1 | 2 =>
      println("d")
  }
}

However, this one works somehow:

import scala.annotation.switch

object Test {
  def foo4(x: Int) = (x: @switch) match {
    case 1 =>
      println("e")
    case 2 | 3 =>
      println("f")
  }
}

@nicolasstucki
Copy link
Contributor

@smarter, when there are 1 or 2 (maybe 3 with default) branches in the pattern match the pattern is always compiled with if/else even if it could potentially do a switch. That is why the first ones fail the @switch tests. We should probably emit a better warning message or just disregard it in those cases.

@@ -18,7 +18,7 @@ object Test extends App {
case _ => 4
}

val x3 = (x: @switch) match {
val x3 = x match {
case '0' if x > 0 => 0
Copy link
Member

Choose a reason for hiding this comment

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

scalac supports emitting switch when cases contain conditions, it translates something like:

  def foo(x: Int, cond: Boolean) = x match {
    case 1 if cond =>
      println("1")
    case 2 =>
      println("2")
    case 3 =>
      println("3")
    case _ =>
      println("4")
  }

to

      x1 match {
        case 1 => if (cond)
          scala.Predef.println("1")
        else
          default5()
        case 2 => scala.Predef.println("2")
        case 3 => scala.Predef.println("3")
        case _ => default5(){
          scala.Predef.println("4")
        }
      }

Is this an intended limitation of Dotty @switch, or something that still needs to be implemented?

Copy link
Contributor

Choose a reason for hiding this comment

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

This was supposed to go in the local optimizations. I made an implementation of this a while ago but I do not know if it went into Dotty or just stayed in the linker.

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 it would make sense to have it by default. Could you open an issue so we keep track of it?

Copy link
Member

Choose a reason for hiding this comment

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

Could you open an issue so we keep track of it?

Turns out there's already one: #1313

@smarter smarter requested a review from nicolasstucki January 4, 2018 14:24
def typesInCases(cdefs: List[CaseDef]): List[Type] =
cdefs.flatMap(cdef => typesInPattern(cdef.pat))
def numTypes(cdefs: List[CaseDef]): Int =
typesInCases(cdefs).toSet.size: Int // without the type ascription, testPickling fails because of #2840.
Copy link
Contributor

Choose a reason for hiding this comment

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

#2840 is fixed, it should be safe to remove the ascription

@nicolasstucki
Copy link
Contributor

This PR needs a rebase

The test code counted the number of different types in all patterns,
but it needs to account for alternative patterns as well.
The tests changed in this commit now caused switch warnings (which
was correct). Remove the @switch annotation to avoid the warning.
@odersky odersky merged commit 691f868 into scala:master Jan 14, 2018
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