diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index a531726fe395..d43a3b8112f0 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -96,9 +96,16 @@ trait TreeAndTypeAnalysis extends Debugging { val parentSubtypes = tp.parents.flatMap(parent => enumerateSubtypes(parent, grouped)) if (parentSubtypes exists (_.nonEmpty)) { // If any of the parents is enumerable, then the refinement type is enumerable. - // We must only include subtypes of the parents that conform to `tp`. - // See neg/virtpatmat_exhaust_compound.scala for an example. - parentSubtypes map (_.filter(_ <:< tp)) + // We must only include subtypes of the parents that conform to `tpApprox`. + // See neg/virtpatmat_exhaust_compound.scala and pos/t9657.scala for examples. + val approximateTypeSkolemsToUpperBound = new TypeMap { // from approximateAbstracts + def apply(tp: Type): Type = tp.dealiasWiden match { + case TypeRef(_, sym, _) if sym.isTypeSkolem => tp.upperBound + case _ => mapOver(tp) + } + } + val tpApprox = approximateTypeSkolemsToUpperBound(tp) + parentSubtypes.map(_.filter(_ <:< tpApprox)) } else Nil // make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte diff --git a/test/files/pos/t9657.scala b/test/files/pos/t9657.scala new file mode 100644 index 000000000000..eb51a41b0f37 --- /dev/null +++ b/test/files/pos/t9657.scala @@ -0,0 +1,21 @@ +// scalac: -Werror +sealed trait PowerSource +case object Petrol extends PowerSource +case object Pedal extends PowerSource + +sealed abstract class Vehicle { type A <: PowerSource } +case object Bicycle extends Vehicle { type A = Pedal.type } +case class Bus(fuel: Int) extends Vehicle { type A = Petrol.type } +case class Car(fuel: Int) extends Vehicle { type A = Petrol.type } + +object Test { + def refuel[P <: Petrol.type](vehicle: Vehicle { type A = P }): Vehicle = vehicle match { + case Car(_) => Car(100) + case Bus(_) => Bus(100) // was: "unreachable code" warning + } + + def main(args: Array[String]): Unit = { + println(refuel(Car(100))) + println(refuel(Bus(5))) + } +}