diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-03-23 09:48:33 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-03-23 11:26:39 +0100 |
commit | 2e0be8323bdef5582a0f5af84b3de83fcc338be4 (patch) | |
tree | 90486886b1888185fdba7b9b5bfb57384545c54e /src | |
parent | 62dd51a79ef1b1c240c1eb1e97c330347f842d4c (diff) | |
download | scala-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.scala | 16 |
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) |