Skip to content

Commit dbc66a4

Browse files
committed
Fix #5402: Avoid duplicate labels in switches
1 parent 4d10f68 commit dbc66a4

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -711,9 +711,14 @@ object PatternMatcher {
711711
(tpe isRef defn.ShortClass) ||
712712
(tpe isRef defn.CharClass)
713713

714-
def isIntConst(tree: Tree) = tree match {
715-
case Literal(const) => const.isIntRange
716-
case _ => false
714+
val seen = mutable.Set[Int]()
715+
716+
def isNewIntConst(tree: Tree) = tree match {
717+
case Literal(const) if const.isIntRange && !seen.contains(const.intValue) =>
718+
seen += const.intValue
719+
true
720+
case _ =>
721+
false
717722
}
718723

719724
// An extractor to recover the shape of plans that can become alternatives
@@ -725,7 +730,7 @@ object PatternMatcher {
725730
val alts = List.newBuilder[Tree]
726731
def rec(innerPlan: Plan): Boolean = innerPlan match {
727732
case SeqPlan(TestPlan(EqualTest(tree), scrut, _, ReturnPlan(`innerLabel`)), tail)
728-
if scrut === scrutinee && isIntConst(tree) =>
733+
if scrut === scrutinee && isNewIntConst(tree) =>
729734
alts += tree
730735
rec(tail)
731736
case ReturnPlan(`outerLabel`) =>
@@ -746,7 +751,7 @@ object PatternMatcher {
746751

747752
def recur(plan: Plan): List[(List[Tree], Plan)] = plan match {
748753
case SeqPlan(testPlan @ TestPlan(EqualTest(tree), scrut, _, ons), tail)
749-
if scrut === scrutinee && isIntConst(tree) && !canFallThrough(ons) =>
754+
if scrut === scrutinee && !canFallThrough(ons) && isNewIntConst(tree) =>
750755
(tree :: Nil, ons) :: recur(tail)
751756
case SeqPlan(AlternativesPlan(alts, ons), tail) =>
752757
(alts, ons) :: recur(tail)

tests/pos/i5402.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
object Main {
2+
val a: Int = 4
3+
a match {
4+
case 1 => println("1")
5+
case 1 | 2 => println("1 or 2")
6+
}
7+
8+
a match {
9+
case 1 => 1
10+
case 0 | 0 => 0
11+
case 2 | 2 | 2 | 3 | 2 | 3 => 0
12+
case 4 | (_ @ 4) => 0
13+
case _ => -1
14+
}
15+
16+
a match {
17+
case 1 => 1
18+
case 0 | 0 => 0
19+
case 2 | 2 | 2 | 3 | 2 | 3 => 0
20+
case _ => -1
21+
}
22+
23+
a match {
24+
case 0 | 1 => 0
25+
case 1 => 1
26+
}
27+
}

0 commit comments

Comments
 (0)