Closed
Description
Scala emits a switch instruction when matching on Int
or String
but not when matching on a union of those types.
Compiler version
3.3.3, 3.4.1
Minimized code
def matchInt(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case 3 => "three"
case 4 => "four"
case 5 => "five"
}
def matchIntUnion(x: 1 | 2 | 3 | 4 | 5): String = x match {
case 1 => "one"
case 2 => "two"
case 3 => "three"
case 4 => "four"
case 5 => "five"
}
def matchString(s: String): Int = s match {
case "one" => 1
case "two" => 2
case "three" => 3
case "four" => 4
case "five" => 5
}
def matchStringUnion(s: "one" | "two" | "three" | "four" | "five"): Int = s match {
case "one" => 1
case "two" => 2
case "three" => 3
case "four" => 4
case "five" => 5
}
Output
The above code (de)compiles to:
public String matchInt(final int x) {
switch (x) {
case 1:
return "one";
case 2:
return "two";
case 3:
return "three";
case 4:
return "four";
case 5:
return "five";
default:
throw new MatchError(BoxesRunTime.boxToInteger(x));
}
}
public String matchIntUnion(final int x) {
if (1 == x) {
return "one";
} else if (2 == x) {
return "two";
} else if (3 == x) {
return "three";
} else if (4 == x) {
return "four";
} else if (5 == x) {
return "five";
} else {
throw new MatchError(BoxesRunTime.boxToInteger(x));
}
}
public int matchString(final String s) {
switch (s == null ? 0 : s.hashCode()) {
case 110182:
if ("one".equals(s)) {
return 1;
}
break;
case 115276:
if ("two".equals(s)) {
return 2;
}
break;
case 3143346:
if ("five".equals(s)) {
return 5;
}
break;
case 3149094:
if ("four".equals(s)) {
return 4;
}
break;
case 110339486:
if ("three".equals(s)) {
return 3;
}
}
throw new MatchError(s);
}
public int matchStringUnion(final String s) {
if ("one".equals(s)) {
return 1;
} else if ("two".equals(s)) {
return 2;
} else if ("three".equals(s)) {
return 3;
} else if ("four".equals(s)) {
return 4;
} else if ("five".equals(s)) {
return 5;
} else {
throw new MatchError(s);
}
}
Expectation
Emit a switch instruction when all members of the union share a base type with a switch-compatible type. For example:
- matching on
1 | 2 | 3 | 4 | 5
can emit a switch because the union widens toInt
- matching on
"one" | "two" | "three" | "four" | "five"
can emit a switch because the union widens toString
- matching on
'a' | 'b' | 'c'
can emit a switch because the union widens toChar
- matching on
1 | 2 | 3 | "four" | "five"
cannot emit a switch
Byte
or Short
can also be used in a switch but there's no syntax to make literals for those types.