Skip to content

Commit c569f23

Browse files
committed
address review feedback
1 parent 61414c2 commit c569f23

File tree

1 file changed

+30
-11
lines changed
  • compiler/src/dotty/tools/dotc/transform/patmat

1 file changed

+30
-11
lines changed

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,13 @@ trait SpaceLogic {
101101
/** Display space in string format */
102102
def show(sp: Space): String
103103

104-
/** Simplify space using the laws, there's no nested union after simplify */
104+
/** Simplify space using the laws, there's no nested union after simplify
105+
*
106+
* @param aggressive if true and OR space has less than 5 components, `simplify` will
107+
* collapse `sp1 | sp2` to `sp1` if `sp2` is a subspace of `sp1`.
108+
*
109+
* This reduces noise in counterexamples.
110+
*/
105111
def simplify(space: Space, aggressive: Boolean = false): Space = space match {
106112
case Kon(tp, spaces) =>
107113
val sp = Kon(tp, spaces.map(simplify(_)))
@@ -160,7 +166,7 @@ trait SpaceLogic {
160166
ss.forall(isSubspace(_, b))
161167
case (Typ(tp1, _), Typ(tp2, _)) =>
162168
isSubType(tp1, tp2)
163-
case (Typ(tp1, _), Or(ss)) => // optimization
169+
case (Typ(tp1, _), Or(ss)) => // optimization: don't go to subtraction too early
164170
ss.exists(isSubspace(a, _)) || tryDecompose1(tp1)
165171
case (_, Or(_)) =>
166172
simplify(minus(a, b)) == Empty
@@ -323,11 +329,11 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
323329
import SpaceEngine._
324330
import tpd._
325331

326-
private val scalaSomeClass = ctx.requiredClassRef("scala.Some".toTypeName).symbol.asClass
332+
private val scalaSomeClass = ctx.requiredClass("scala.Some".toTypeName)
327333
private val scalaSeqFactoryClass = ctx.requiredClass("scala.collection.generic.SeqFactory".toTypeName)
328334
private val scalaListType = ctx.requiredClassRef("scala.collection.immutable.List".toTypeName)
329335
private val scalaNilType = ctx.requiredModuleRef("scala.collection.immutable.Nil".toTermName)
330-
private val scalaConType = ctx.requiredClassRef("scala.collection.immutable.::".toTypeName)
336+
private val scalaConsType = ctx.requiredClassRef("scala.collection.immutable.::".toTypeName)
331337

332338
/** Checks if it's possible to create a trait/class which is a subtype of `tp`.
333339
*
@@ -442,7 +448,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
442448
(pats, Typ(scalaNilType, false))
443449

444450
items.foldRight[Space](zero) { (pat, acc) =>
445-
Kon(scalaConType.appliedTo(pats.head.tpe.widen), project(pat) :: acc :: Nil)
451+
Kon(scalaConsType.appliedTo(pats.head.tpe.widen), project(pat) :: acc :: Nil)
446452
}
447453
}
448454

@@ -469,6 +475,19 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
469475
/** Is `tp1` a subtype of `tp2`? */
470476
def isSubType(tp1: Type, tp2: Type): Boolean = {
471477
// check SI-9657 and tests/patmat/gadt.scala
478+
//
479+
// `erase` is a walkaround to make the following code pass the check:
480+
//
481+
// def f(e: Either[Int, String]) = e match {
482+
// case Left(i) => i
483+
// case Right(s) => 0
484+
// }
485+
//
486+
// The problem is that when decompose `Either[Int, String]`, `Type.wrapIfMember`
487+
// only refines the type member inherited from `Either` -- it's complex to refine
488+
// the type members in `Left` and `Right`.
489+
//
490+
// FIXME: remove this hack
472491
val res = tp1 <:< erase(tp2)
473492
debug.println(s"${tp1.show} <:< ${tp2.show} = $res")
474493
res
@@ -509,7 +528,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
509528
case space => List(space)
510529
}
511530
case OrType(tp1, tp2) => List(Typ(tp1, true), Typ(tp2, true))
512-
case tp if tp =:= ctx.definitions.BooleanType =>
531+
case tp if tp.isRef(defn.BooleanClass) =>
513532
List(
514533
Typ(ConstantType(Constant(true)), true),
515534
Typ(ConstantType(Constant(false)), true)
@@ -568,7 +587,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
568587
val and = dealiasedTp.asInstanceOf[AndType]
569588
canDecompose(and.tp1) || canDecompose(and.tp2)
570589
}) ||
571-
tp =:= ctx.definitions.BooleanType ||
590+
tp.isRef(defn.BooleanClass) ||
572591
tp.classSymbol.is(allOf(Enum, Sealed)) // Enum value doesn't have Sealed flag
573592

574593
debug.println(s"decomposable: ${tp.show} = $res")
@@ -632,9 +651,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
632651

633652
if (ctx.definitions.isTupleType(tp))
634653
signature(tp).map(_ => "_").mkString("(", ", ", ")")
635-
else if (sym.showFullName == "scala.collection.immutable.List")
654+
else if (scalaListType.isRef(sym))
636655
if (mergeList) "_*" else "_: List"
637-
else if (sym.showFullName == "scala.collection.immutable.::")
656+
else if (scalaConsType.isRef(sym))
638657
if (mergeList) "_" else "List(_)"
639658
else if (tp.classSymbol.is(CaseClass))
640659
// use constructor syntax for case class
@@ -646,7 +665,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
646665
case Kon(tp, params) =>
647666
if (ctx.definitions.isTupleType(tp))
648667
"(" + params.map(doShow(_)).mkString(", ") + ")"
649-
else if (tp.widen.classSymbol.showFullName == "scala.collection.immutable.::")
668+
else if (tp.isRef(scalaConsType.symbol))
650669
if (mergeList) params.map(doShow(_, mergeList)).mkString(", ")
651670
else params.map(doShow(_, true)).filter(_ != "Nil").mkString("List(", ", ", ")")
652671
else
@@ -673,7 +692,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
673692
val and = tp.asInstanceOf[AndType]
674693
isCheckable(and.tp1) || isCheckable(and.tp2)
675694
}) ||
676-
tp.typeSymbol == ctx.definitions.BooleanType.typeSymbol ||
695+
tp.isRef(defn.BooleanClass) ||
677696
tp.typeSymbol.is(Enum) ||
678697
canDecompose(tp) ||
679698
(defn.isTupleType(tp) && tp.dealias.argInfos.exists(isCheckable(_)))

0 commit comments

Comments
 (0)