@@ -769,16 +769,49 @@ object PatternMatcher {
769
769
}
770
770
771
771
/** Emit cases of a switch */
772
- private def emitSwitchCases (cases : List [(List [Tree ], Plan )]): List [CaseDef ] = ( cases : @ unchecked) match {
773
- case (alts, ons) :: cases1 =>
774
- val pat = alts match {
775
- case alt :: Nil => alt
776
- case Nil => Underscore (defn. IntType ) // default case
777
- case _ => Alternative (alts )
772
+ private def emitSwitchCases (cases : List [(List [Tree ], Plan )]): List [CaseDef ] = cases.foldLeft(( List [ CaseDef ](), List [ Tree ]())) {
773
+ case ((prev, collected), (alts, ons)) =>
774
+ val c = collectCases(collected, alts)
775
+ c match {
776
+ case Some ((pat, col)) => ( CaseDef (pat, EmptyTree , emit(ons)) :: prev, col ::: collected)
777
+ case None => (prev, collected )
778
778
}
779
- CaseDef (pat, EmptyTree , emit(ons)) :: emitSwitchCases(cases1)
780
- case nil =>
781
- Nil
779
+ }._1
780
+
781
+ /** Flattens the tree of patterns into a tree and collect all the alternative patterns in a list
782
+ * return None if the pattern is redundant
783
+ */
784
+ private def collectCases (existingPatterns : List [Tree ], alts : List [Tree ]): Option [(Tree , List [Tree ])] = {
785
+ alts match {
786
+ case Nil => Some ((Underscore (defn.IntType ), Nil ))
787
+ case _ => mapCases(removeRedundantCases(existingPatterns, alts))
788
+ }
789
+ }
790
+
791
+ private def mapCases (alts : List [Tree ]): Option [(Tree , List [Tree ])] = alts match {
792
+ case alt :: Nil => Some ((alt, alt :: Nil ))
793
+ case Nil => None
794
+ case _ => Some ((Alternative (alts), alts))
795
+ }
796
+
797
+ private def isCaseRedundant (previousCases : List [Tree ], `case` : Tree ): Boolean =
798
+ previousCases.exists(_ === `case`)
799
+
800
+ /** Remove cases that already appear in the same pattern or in previous patterns */
801
+ private def removeRedundantCases (previousCases : List [Tree ], cases : List [Tree ]): List [Tree ] = cases.foldLeft(List [Tree ]()) {
802
+ case (cases, alt) =>
803
+ if (isCaseRedundant(cases, alt) || isCaseRedundant(previousCases, alt)) {
804
+ cases
805
+ } else {
806
+ alt :: cases
807
+ }
808
+ }
809
+
810
+ /** Flatten a list of patterns into a single tree */
811
+ private def simplifyCases (alts : List [Tree ]): Tree = alts match {
812
+ case alt :: Nil => alt
813
+ case Nil => Underscore (defn.IntType ) // default case
814
+ case _ => Alternative (alts)
782
815
}
783
816
784
817
/** If selfCheck is `true`, used to check whether a tree gets generated twice */
0 commit comments