diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index ee17927a2598..3f9f7d3143af 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -584,10 +584,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { // precondition: `tp1` should have the shape `path.Child`, thus `ThisType` is always covariant val thisTypeMap = new TypeMap { def apply(t: Type): Type = t match { - case tp @ ThisType(tref) if !tref.symbol.isStaticOwner && !tref.symbol.is(Module) => - // TODO: stackoverflow here - // newTypeVar(TypeBounds.upper(mapOver(tp.underlying))) - newTypeVar(TypeBounds.upper(mapOver(tref & tref.classSymbol.asClass.givenSelfType))) + case tp @ ThisType(tref) if !tref.symbol.isStaticOwner => + if (tref.symbol.is(Module)) mapOver(tref) + else newTypeVar(TypeBounds.upper(tp.underlying)) case _ => mapOver(t) } @@ -596,7 +595,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { // replace type parameter references with bounds val typeParamMap = new TypeMap { def apply(t: Type): Type = t match { - case tp: TypeRef if tp.symbol.is(TypeParam) && tp.underlying.isInstanceOf[TypeBounds] => // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala val exposed = @@ -611,13 +609,32 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { } } + // replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala + val instUndetMap = new TypeMap { + def apply(t: Type): Type = t match { + case tvar: TypeVar if !tvar.isInstantiated => WildcardType(tvar.origin.underlying.bounds) + case _ => mapOver(t) + } + } + + val force = new ForceDegree.Value( + tvar => !(ctx.typerState.constraint.entry(tvar.origin) eq tvar.origin.underlying), + minimizeAll = false + ) + val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) } val protoTp1 = thisTypeMap(tp1.appliedTo(tvars)) - if (protoTp1 <:< tp2 && isFullyDefined(protoTp1, ForceDegree.noBottom)) protoTp1 + if (protoTp1 <:< tp2) { + if (isFullyDefined(protoTp1, force)) protoTp1 + else instUndetMap(protoTp1) + } else { val protoTp2 = typeParamMap(tp2) - if (protoTp1 <:< protoTp2 && isFullyDefined(protoTp1 & protoTp2, ForceDegree.noBottom)) protoTp1 + if (protoTp1 <:< protoTp2) { + if (isFullyDefined(AndType(protoTp1, protoTp2), force)) protoTp1 + else instUndetMap(protoTp1) + } else { debug.println(s"$protoTp1 <:< $protoTp2 = false") NoType diff --git a/tests/patmat/3333.check b/tests/patmat/3333.check new file mode 100644 index 000000000000..488cf35a2b70 --- /dev/null +++ b/tests/patmat/3333.check @@ -0,0 +1 @@ +10: Pattern Match Exhaustivity: _: IntNumber, NotNaN \ No newline at end of file diff --git a/tests/patmat/3333.scala b/tests/patmat/3333.scala new file mode 100644 index 000000000000..48812d0e8575 --- /dev/null +++ b/tests/patmat/3333.scala @@ -0,0 +1,14 @@ +sealed trait IntegralNumber + +object IntegralNumber { + object NaN extends IntegralNumber + object NotNaN extends IntegralNumber + + sealed abstract class FiniteNumberImpl[N](val value: N) extends IntegralNumber + sealed class IntNumber(value: Int) extends FiniteNumberImpl[Int](value) + + def test(o: IntegralNumber) = o match { + case NaN => -1 + } + +} diff --git a/tests/patmat/3455.check b/tests/patmat/3455.check new file mode 100644 index 000000000000..6421d3806518 --- /dev/null +++ b/tests/patmat/3455.check @@ -0,0 +1 @@ +11: Pattern Match Exhaustivity: Decimal diff --git a/tests/patmat/3455.scala b/tests/patmat/3455.scala new file mode 100644 index 000000000000..720b45bc08a7 --- /dev/null +++ b/tests/patmat/3455.scala @@ -0,0 +1,14 @@ +trait AxisCompanion { + sealed trait Format + object Format { + case object Decimal extends Format + case object Integer extends Format + } +} +object Axis extends AxisCompanion +class Axis { + import Axis._ + def test( f: Format ) = f match { + case Format.Integer => "Int" + } +} diff --git a/tests/patmat/3469.scala b/tests/patmat/3469.scala new file mode 100644 index 000000000000..8abad0252d11 --- /dev/null +++ b/tests/patmat/3469.scala @@ -0,0 +1,9 @@ +object O { + sealed trait Trait[+A] { type T } + case class CaseClass[+A](a: A) extends Trait[A] { type T = Nothing } + + def id[TT, A](v: Trait[A] { type T = TT }): Trait[A] { type T = TT } = + v match { + case CaseClass(a) => CaseClass(a) + } +} \ No newline at end of file