Skip to content

Commit bc46312

Browse files
committed
Adjust behaviour of TypeComparer.either for GADTflexible
1 parent 53a571b commit bc46312

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,
@@ -954,6 +962,8 @@ object Contexts {
954962

955963
override def constr_println(msg: => String): Unit = gadtsConstr.println(msg)
956964

965+
override def toText(printer: Printer): Texts.Text = constraint.toText(printer)
966+
957967
override def debugBoundsDescription(implicit ctx: Context): String = {
958968
val sb = new mutable.StringBuilder
959969
sb ++= constraint.show
@@ -973,6 +983,7 @@ object Contexts {
973983
override def fullBounds(sym: Symbol)(implicit ctx: Context): TypeBounds = null
974984
override def contains(sym: Symbol)(implicit ctx: Context) = false
975985
override def approximation(sym: Symbol, fromBelow: Boolean)(implicit ctx: Context): Type = unsupported("EmptyGADTMap.approximation")
986+
override def toText(printer: Printer): Texts.Text = "EmptyGADTMap"
976987
override def debugBoundsDescription(implicit ctx: Context): String = "EmptyGADTMap"
977988
override def fresh = new SmartGADTMap
978989
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
@@ -1219,16 +1219,52 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
12191219
*/
12201220
private def either(op1: => Boolean, op2: => Boolean): Boolean = {
12211221
val preConstraint = constraint
1222-
op1 && {
1223-
val leftConstraint = constraint
1224-
constraint = preConstraint
1225-
if (!(op2 && subsumes(leftConstraint, constraint, preConstraint))) {
1226-
if (constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint))
1227-
constr.println(i"CUT - prefer $leftConstraint over $constraint")
1228-
constraint = leftConstraint
1229-
}
1230-
true
1231-
} || op2
1222+
1223+
if (ctx.mode.is(Mode.GADTflexible)) {
1224+
val preGadt = ctx.gadt.fresh
1225+
// if GADTflexible mode is on, we always have a SmartGADTMap
1226+
val pre = preGadt.asInstanceOf[SmartGADTMap]
1227+
if (op1) {
1228+
val leftConstraint = constraint
1229+
val leftGadt = ctx.gadt.fresh
1230+
constraint = preConstraint
1231+
ctx.gadt.restore(preGadt)
1232+
if (op2) {
1233+
if (pre.subsumes(leftGadt, ctx.gadt, preGadt) && subsumes(leftConstraint, constraint, preConstraint)) {
1234+
gadts.println(i"GADT CUT - prefer ${ctx.gadt} over $leftGadt")
1235+
constr.println(i"CUT - prefer $constraint over $leftConstraint")
1236+
true
1237+
} else if (pre.subsumes(ctx.gadt, leftGadt, preGadt) && subsumes(constraint, leftConstraint, preConstraint)) {
1238+
gadts.println(i"GADT CUT - prefer $leftGadt over ${ctx.gadt}")
1239+
constr.println(i"CUT - prefer $leftConstraint over $constraint")
1240+
constraint = leftConstraint
1241+
ctx.gadt.restore(leftGadt)
1242+
true
1243+
} else {
1244+
gadts.println(i"GADT CUT - no constraint is preferable, reverting to $preGadt")
1245+
constr.println(i"CUT - no constraint is preferable, reverting to $preConstraint")
1246+
constraint = preConstraint
1247+
ctx.gadt.restore(preGadt)
1248+
true
1249+
}
1250+
} else {
1251+
constraint = leftConstraint
1252+
ctx.gadt.restore(leftGadt)
1253+
true
1254+
}
1255+
} else op2
1256+
} else {
1257+
op1 && {
1258+
val leftConstraint = constraint
1259+
constraint = preConstraint
1260+
if (!(op2 && subsumes(leftConstraint, constraint, preConstraint))) {
1261+
if (constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint))
1262+
constr.println(i"CUT - prefer $leftConstraint over $constraint")
1263+
constraint = leftConstraint
1264+
}
1265+
true
1266+
} || op2
1267+
}
12321268
}
12331269

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

0 commit comments

Comments
 (0)