summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-03-23 09:48:33 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-03-23 11:26:39 +0100
commit2e0be8323bdef5582a0f5af84b3de83fcc338be4 (patch)
tree90486886b1888185fdba7b9b5bfb57384545c54e /src
parent62dd51a79ef1b1c240c1eb1e97c330347f842d4c (diff)
downloadscala-2e0be8323bdef5582a0f5af84b3de83fcc338be4.tar.gz
scala-2e0be8323bdef5582a0f5af84b3de83fcc338be4.tar.bz2
scala-2e0be8323bdef5582a0f5af84b3de83fcc338be4.zip
SI-7290 Discard duplicates in switchable alternative patterns.
The pattern matcher must not allow duplicates to hit the backend when generating switches. It already eliminates then if they appear on different cases (with an unreachability warning.) This commit does the same for duplicated literal patterns in an alternative pattern: discard and warn.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
index dcf2413b15..23889058d3 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
@@ -22,7 +22,7 @@ import scala.reflect.internal.util.NoPosition
trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
import PatternMatchingStats._
import global.{Tree, Type, Symbol, NoSymbol, CaseDef, atPos,
- ConstantType, Literal, Constant, gen, EmptyTree,
+ ConstantType, Literal, Constant, gen, EmptyTree, distinctBy,
Typed, treeInfo, nme, Ident,
Apply, If, Bind, lub, Alternative, deriveCaseDef, Match, MethodType, LabelDef, TypeTree, Throw}
@@ -442,7 +442,7 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
case SwitchableTreeMaker(pattern) :: GuardAndBodyTreeMakers(guard, body) =>
Some(CaseDef(pattern, guard, body))
// alternatives
- case AlternativesTreeMaker(_, altss, _) :: GuardAndBodyTreeMakers(guard, body) if alternativesSupported =>
+ case AlternativesTreeMaker(_, altss, pos) :: GuardAndBodyTreeMakers(guard, body) if alternativesSupported =>
val switchableAlts = altss map {
case SwitchableTreeMaker(pattern) :: Nil =>
Some(pattern)
@@ -452,7 +452,17 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
// succeed if they were all switchable
sequence(switchableAlts) map { switchableAlts =>
- CaseDef(Alternative(switchableAlts), guard, body)
+ def extractConst(t: Tree) = t match {
+ case Literal(const) => const
+ case _ => t
+ }
+ // SI-7290 Discard duplicate alternatives that would crash the backend
+ def distinctAlts = distinctBy(switchableAlts)(extractConst)
+ if (distinctAlts.size < switchableAlts.size) {
+ val duplicated = switchableAlts.groupBy(extractConst).flatMap(_._2.drop(1))
+ global.currentUnit.warning(pos, s"Pattern contains duplicate alternatives: ${duplicated.mkString(", ")}")
+ }
+ CaseDef(Alternative(distinctAlts), guard, body)
}
case _ =>
// debug.patmat("can't emit switch for "+ makers)