132
132
import Flags.{ MUTABLE, ABSTRACT, SEALED }
134
private case class Combo(index: Int, sym: Symbol) {
135
val isBaseClass = sym.tpe.baseClasses.toSet
137
// is this combination covered by the given pattern?
138
def isCovered(p: Pattern) = {
139
def coversSym = isBaseClass(decodedEqualsType(p.tpe).typeSymbol)
142
case _: UnApply | _: ArrayValue => true
143
case x => p.isDefault || coversSym
134
private case class Combo(index: Int, sym: Symbol) { }
148
136
/* True if the patterns in 'row' cover the given type symbol combination, and has no guard. */
149
137
private def rowCoversCombo(row: Row, combos: List[Combo]) =
150
row.guard.isEmpty && (combos forall (c => c isCovered row.pats(c.index)))
138
row.guard.isEmpty && combos.forall(c => row.pats(c.index) covers c.sym)
152
140
private def requiresExhaustive(sym: Symbol) = {
153
141
(sym.isMutable) && // indicates that have not yet checked exhaustivity
154
142
!(sym hasFlag NO_EXHAUSTIVE) && // indicates @unchecked
155
143
(sym.tpe.typeSymbol.isSealed) &&
156
!isValueClass(sym.tpe.typeSymbol) // make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte
144
!isPrimitiveValueClass(sym.tpe.typeSymbol) // make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte
159
147
private lazy val inexhaustives: List[List[Combo]] = {
162
150
val collected = toCollect map { case (pv, i) =>
163
151
// okay, now reset the flag
164
152
pv.sym resetFlag MUTABLE
165
// have to filter out children which cannot match: see ticket #3683 for an example
166
val kids = pv.tpe.typeSymbol.sealedDescendants filter (_.tpe matchesPattern pv.tpe)
155
pv.tpe.typeSymbol.sealedDescendants.toList sortBy (_.sealedSortName)
156
// symbols which are both sealed and abstract need not be covered themselves, because
157
// all of their children must be and they cannot otherwise be created.
158
filterNot (x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x))
159
// have to filter out children which cannot match: see ticket #3683 for an example
160
filter (_.tpe matchesPattern pv.tpe)