Skip to content

Fix #3588: Do not emit switch when matching on Any #3589

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 1 commit into from
Dec 1, 2017

Conversation

nicolasstucki
Copy link
Contributor

No description provided.

@nicolasstucki
Copy link
Contributor Author

As done scalac.

val switchCases = collectSwitchCases(plan)
val switchCases =
if (plan.scrutinee.tpe.widen.classSymbol == defn.AnyClass) Nil
else collectSwitchCases(plan)
Copy link
Contributor

@allanrenucci allanrenucci Nov 29, 2017

Choose a reason for hiding this comment

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

I think it should be part of collectSwitchCases and maybe use the already defined isSwitchableType function

@@ -795,7 +795,8 @@ object PatternMatcher {
(tpe isRef defn.IntClass) ||
(tpe isRef defn.ByteClass) ||
(tpe isRef defn.ShortClass) ||
(tpe isRef defn.CharClass)
(tpe isRef defn.CharClass) ||
(tpe isRef defn.StringClass)
Copy link
Contributor

Choose a reason for hiding this comment

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

Scalac does not emit switch for String. Is it a limitation we can lift? Java supports switch for String since JDK 7

Copy link
Contributor

@vitorsvieira vitorsvieira Nov 29, 2017

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have code testing that strings are switchable. I saw that failure in the first commit.

Copy link
Member

Choose a reason for hiding this comment

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

Is support for switching on strings actually implemented somewhere in the compiler? The Java support is implemented by desugaring them into two switch statements on integers, there is no bytecode-level support for switching on strings.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We currenly do exactly the same as in scalac. We desugar it into if/then/else

@@ -64,7 +64,7 @@ class ShowTests {
case class Car(model: String, manufacturer: String, year: Int)

assertEquals("Car(Mustang,Ford,1967)", Car("Mustang", "Ford", 1967).show)
assertEquals("Map()", Map().show)
assertEquals("Map()", Map[String, String]().show)
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the warning emitted?

The test actually expect something of type Map[Nothing, Nothing].

(tpe isRef defn.ByteClass) ||
(tpe isRef defn.ShortClass) ||
(tpe isRef defn.CharClass)

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 with isSwitchableType and it seems to work if you widen before calling it:

isSwitchableType(scrutinee.tpe.widen)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

case A(3) =>
case _ =>
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I would add two more tests:

  • a pos test compiled with -Xfatal-warnings:
class Test {
  def test(x: 1) = (x: @annotation.switch) match {
    case 1 => 1
    case 2 => 2
    case 3 => 3
  }
}
  • a neg test compiled with -Xfatal-warnings:
object Test {
  case class IntAnyVal(x: Int) extends AnyVal

  def test(x: IntAnyVal) = (x: @annotation.switch) match { //error: warning: could not emit switch
    case IntAnyVal(1) => 1
    case IntAnyVal(2) => 2
    case IntAnyVal(3) => 3
    case _ => 4
  }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

@allanrenucci allanrenucci left a comment

Choose a reason for hiding this comment

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

LGTM. I think you can squash the commits since the history is not meaningful.

@allanrenucci allanrenucci merged commit e8a6378 into scala:master Dec 1, 2017
@allanrenucci allanrenucci deleted the fix-#3588 branch December 1, 2017 15:54
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.

4 participants