Skip to content

Commit 3df2c0f

Browse files
committed
Adjust behaviour of TypeComparer.either for GADTflexible
1 parent f5a1ef2 commit 3df2c0f

File tree

3 files changed

+59
-12
lines changed

3 files changed

+59
-12
lines changed

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ object Contexts {
775775
else assert(thread == Thread.currentThread(), "illegal multithreaded access to ContextBase")
776776
}
777777

778-
sealed abstract class GADTMap {
778+
sealed abstract class GADTMap extends Showable {
779779
def addEmptyBounds(sym: Symbol)(implicit ctx: Context): Unit
780780
def addBound(sym: Symbol, bound: Type, isUpper: Boolean)(implicit ctx: Context): Boolean
781781
def isLess(sym1: Symbol, sym2: Symbol)(implicit ctx: Context): Boolean
@@ -802,6 +802,14 @@ object Contexts {
802802
) extends GADTMap with ConstraintHandling[Context] {
803803
import dotty.tools.dotc.config.Printers.{gadts, gadtsConstr}
804804

805+
def subsumes(left: GADTMap, right: GADTMap, pre: GADTMap)(implicit ctx: Context): Boolean = {
806+
def extractConstraint(g: GADTMap) = g match {
807+
case s: SmartGADTMap => s.constraint
808+
case EmptyGADTMap => OrderingConstraint.empty
809+
}
810+
subsumes(extractConstraint(left), extractConstraint(right), extractConstraint(pre))
811+
}
812+
805813
def this() = this(
806814
myConstraint = new OrderingConstraint(SimpleIdentityMap.Empty, SimpleIdentityMap.Empty, SimpleIdentityMap.Empty),
807815
mapping = SimpleIdentityMap.Empty,
@@ -950,6 +958,8 @@ object Contexts {
950958

951959
override def constr_println(msg: => String): Unit = gadtsConstr.println(msg)
952960

961+
override def toText(printer: Printer): Texts.Text = constraint.toText(printer)
962+
953963
override def debugBoundsDescription(implicit ctx: Context): String = {
954964
val sb = new mutable.StringBuilder
955965
sb ++= constraint.show
@@ -969,6 +979,7 @@ object Contexts {
969979
override def fullBounds(sym: Symbol)(implicit ctx: Context): TypeBounds = null
970980
override def contains(sym: Symbol)(implicit ctx: Context) = false
971981
override def approximation(sym: Symbol, fromBelow: Boolean)(implicit ctx: Context): Type = unsupported("EmptyGADTMap.approximation")
982+
override def toText(printer: Printer): Texts.Text = "EmptyGADTMap"
972983
override def debugBoundsDescription(implicit ctx: Context): String = "EmptyGADTMap"
973984
override def fresh = new SmartGADTMap
974985
override def restore(other: GADTMap): Unit = {

compiler/src/dotty/tools/dotc/core/Mode.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ object Mode {
4949
/** We are in a pattern alternative */
5050
val InPatternAlternative: Mode = newMode(7, "InPatternAlternative")
5151

52-
/** Allow GADTFlexType labelled types to have their bounds adjusted */
52+
/** Infer GADT constraints during type comparisons `A <:< B` */
5353
val GADTflexible: Mode = newMode(8, "GADTflexible")
5454

5555
/** Assume -language:strictEquality */

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,16 +1252,52 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
12521252
*/
12531253
private def either(op1: => Boolean, op2: => Boolean): Boolean = {
12541254
val preConstraint = constraint
1255-
op1 && {
1256-
val leftConstraint = constraint
1257-
constraint = preConstraint
1258-
if (!(op2 && subsumes(leftConstraint, constraint, preConstraint))) {
1259-
if (constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint))
1260-
constr.println(i"CUT - prefer $leftConstraint over $constraint")
1261-
constraint = leftConstraint
1262-
}
1263-
true
1264-
} || op2
1255+
1256+
if (ctx.mode.is(Mode.GADTflexible)) {
1257+
val preGadt = ctx.gadt.fresh
1258+
// if GADTflexible mode is on, we always have a SmartGADTMap
1259+
val pre = preGadt.asInstanceOf[SmartGADTMap]
1260+
if (op1) {
1261+
val leftConstraint = constraint
1262+
val leftGadt = ctx.gadt.fresh
1263+
constraint = preConstraint
1264+
ctx.gadt.restore(preGadt)
1265+
if (op2) {
1266+
if (pre.subsumes(leftGadt, ctx.gadt, preGadt) && subsumes(leftConstraint, constraint, preConstraint)) {
1267+
gadts.println(i"GADT CUT - prefer ${ctx.gadt} over $leftGadt")
1268+
constr.println(i"CUT - prefer $constraint over $leftConstraint")
1269+
true
1270+
} else if (pre.subsumes(ctx.gadt, leftGadt, preGadt) && subsumes(constraint, leftConstraint, preConstraint)) {
1271+
gadts.println(i"GADT CUT - prefer $leftGadt over ${ctx.gadt}")
1272+
constr.println(i"CUT - prefer $leftConstraint over $constraint")
1273+
constraint = leftConstraint
1274+
ctx.gadt.restore(leftGadt)
1275+
true
1276+
} else {
1277+
gadts.println(i"GADT CUT - no constraint is preferable, reverting to $preGadt")
1278+
constr.println(i"CUT - no constraint is preferable, reverting to $preConstraint")
1279+
constraint = preConstraint
1280+
ctx.gadt.restore(preGadt)
1281+
true
1282+
}
1283+
} else {
1284+
constraint = leftConstraint
1285+
ctx.gadt.restore(leftGadt)
1286+
true
1287+
}
1288+
} else op2
1289+
} else {
1290+
op1 && {
1291+
val leftConstraint = constraint
1292+
constraint = preConstraint
1293+
if (!(op2 && subsumes(leftConstraint, constraint, preConstraint))) {
1294+
if (constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint))
1295+
constr.println(i"CUT - prefer $leftConstraint over $constraint")
1296+
constraint = leftConstraint
1297+
}
1298+
true
1299+
} || op2
1300+
}
12651301
}
12661302

12671303
/** Does type `tp1` have a member with name `name` whose normalized type is a subtype of

0 commit comments

Comments
 (0)