Skip to content

Commit f313ad7

Browse files
committed
Make ApproxState a value class
1 parent f01a96a commit f313ad7

File tree

1 file changed

+30
-18
lines changed

1 file changed

+30
-18
lines changed

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

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
107107
assert(isSatisfiable, constraint.show)
108108
}
109109

110-
protected def isSubType(tp1: Type, tp2: Type): Boolean = isSubType(tp1, tp2, Precise)
110+
protected def isSubType(tp1: Type, tp2: Type): Boolean = isSubType(tp1, tp2, NoApprox)
111111

112112
protected def isSubType(tp1: Type, tp2: Type, approx: ApproxState): Boolean = trace(s"isSubType ${traceInfo(tp1, tp2)} $approx", subtyping) {
113113

@@ -289,7 +289,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
289289
def compareTypeParamRef =
290290
ctx.mode.is(Mode.TypevarsMissContext) ||
291291
isSubTypeWhenFrozen(bounds(tp1).hi, tp2) || {
292-
if (canConstrain(tp1) && (approx & HiApprox) == 0)
292+
if (canConstrain(tp1) && !approx.high)
293293
addConstraint(tp1, tp2, fromBelow = false) && flagNothingBound
294294
else thirdTry
295295
}
@@ -355,8 +355,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
355355
GADTusage(tp2.symbol)
356356
}
357357
val tryLowerFirst = frozenConstraint || !isCappable(tp1)
358-
if (tryLowerFirst) isSubType(tp1, lo2, approx | HiApprox) || compareGADT || fourthTry
359-
else compareGADT || fourthTry || isSubType(tp1, lo2, approx | HiApprox)
358+
if (tryLowerFirst) isSubType(tp1, lo2, approx.addHigh) || compareGADT || fourthTry
359+
else compareGADT || fourthTry || isSubType(tp1, lo2, approx.addHigh)
360360

361361
case _ =>
362362
val cls2 = tp2.symbol
@@ -370,7 +370,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
370370
// If `cls2` is parameterized, we are seeing a raw type, so we need to compare only the symbol
371371
return base.typeSymbol == cls2
372372
if (base ne tp1)
373-
return isSubType(base, tp2, if (tp1.isRef(cls2)) approx else approx | LoApprox)
373+
return isSubType(base, tp2, if (tp1.isRef(cls2)) approx else approx.addLow)
374374
}
375375
if (cls2 == defn.SingletonClass && tp1.isStable) return true
376376
}
@@ -397,7 +397,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
397397
if (frozenConstraint) isSubType(tp1, bounds(tp2).lo)
398398
else isSubTypeWhenFrozen(tp1, tp2)
399399
alwaysTrue || {
400-
if (canConstrain(tp2) && (approx & LoApprox) == 0)
400+
if (canConstrain(tp2) && !approx.low)
401401
addConstraint(tp2, tp1.widenExpr, fromBelow = true)
402402
else fourthTry
403403
}
@@ -564,7 +564,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
564564
narrowGADTBounds(tp1, tp2, approx, isUpper = true)) &&
565565
GADTusage(tp1.symbol)
566566
}
567-
isSubType(hi1, tp2, approx | LoApprox) || compareGADT
567+
isSubType(hi1, tp2, approx.addLow) || compareGADT
568568
case _ =>
569569
def isNullable(tp: Type): Boolean = tp.widenDealias match {
570570
case tp: TypeRef => tp.symbol.isNullableClass
@@ -743,7 +743,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
743743
* @param tyconLo The type constructor's lower approximation.
744744
*/
745745
def fallback(tyconLo: Type) =
746-
either(fourthTry, isSubType(tp1, tyconLo.applyIfParameterized(args2), approx | HiApprox))
746+
either(fourthTry, isSubType(tp1, tyconLo.applyIfParameterized(args2), approx.addHigh))
747747

748748
/** Let `tycon2bounds` be the bounds of the RHS type constructor `tycon2`.
749749
* Let `app2 = tp2` where the type constructor of `tp2` is replaced by
@@ -757,7 +757,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
757757
def compareLower(tycon2bounds: TypeBounds, tyconIsTypeRef: Boolean): Boolean =
758758
if (tycon2bounds.lo eq tycon2bounds.hi)
759759
if (tyconIsTypeRef) recur(tp1, tp2.superType)
760-
else isSubType(tp1, tycon2bounds.lo.applyIfParameterized(args2), approx | HiApprox)
760+
else isSubType(tp1, tycon2bounds.lo.applyIfParameterized(args2), approx.addHigh)
761761
else
762762
fallback(tycon2bounds.lo)
763763

@@ -774,7 +774,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
774774
case info2: ClassInfo =>
775775
val base = tp1.baseType(info2.cls)
776776
if (base.exists && base.ne(tp1))
777-
isSubType(base, tp2, if (tp1.isRef(info2.cls)) approx else approx | LoApprox)
777+
isSubType(base, tp2, if (tp1.isRef(info2.cls)) approx else approx.addLow)
778778
else fourthTry
779779
case _ =>
780780
fourthTry
@@ -801,7 +801,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
801801
false
802802
}
803803
canConstrain(param1) && canInstantiate ||
804-
isSubType(bounds(param1).hi.applyIfParameterized(args1), tp2, approx | LoApprox)
804+
isSubType(bounds(param1).hi.applyIfParameterized(args1), tp2, approx.addLow)
805805
case tycon1: TypeRef if tycon1.symbol.isClass =>
806806
false
807807
case tycon1: TypeProxy =>
@@ -817,7 +817,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
817817
if (isCovered(tp1) && isCovered(tp2)) {
818818
//println(s"useless subtype: $tp1 <:< $tp2")
819819
false
820-
} else isSubType(tp1, tp2, approx | LoApprox)
820+
} else isSubType(tp1, tp2, approx.addLow)
821821

822822
def recur(tp1: Type, tp2: Type) = isSubType(tp1, tp2, approx)
823823

@@ -1099,8 +1099,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
10991099
* Test that the resulting bounds are still satisfiable.
11001100
*/
11011101
private def narrowGADTBounds(tr: NamedType, bound: Type, approx: ApproxState, isUpper: Boolean): Boolean = {
1102-
val boundIsPrecise = (approx & (if (isUpper) HiApprox else LoApprox)) == 0
1103-
ctx.mode.is(Mode.GADTflexible) && !frozenConstraint && boundIsPrecise && {
1102+
val boundImprecise = if (isUpper) approx.high else approx.low
1103+
ctx.mode.is(Mode.GADTflexible) && !frozenConstraint && !boundImprecise && {
11041104
val tparam = tr.symbol
11051105
gadts.println(i"narrow gadt bound of $tparam: ${tparam.info} from ${if (isUpper) "above" else "below"} to $bound ${bound.toString} ${bound.isRef(tparam)}")
11061106
if (bound.isRef(tparam)) false
@@ -1621,10 +1621,22 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
16211621

16221622
object TypeComparer {
16231623

1624-
type ApproxState = Int
1625-
val Precise = 0
1626-
val LoApprox = 1
1627-
val HiApprox = 2
1624+
private val LoApprox = 1
1625+
private val HiApprox = 2
1626+
1627+
class ApproxState(private val bits: Int) extends AnyVal {
1628+
override def toString = {
1629+
val lo = if ((bits & LoApprox) != 0) "LoApprox" else ""
1630+
val hi = if ((bits & HiApprox) != 0) "HiApprox" else ""
1631+
lo ++ hi
1632+
}
1633+
def addLow = new ApproxState(bits | LoApprox)
1634+
def addHigh = new ApproxState(bits | HiApprox)
1635+
def low = (bits & LoApprox) != 0
1636+
def high = (bits & HiApprox) != 0
1637+
}
1638+
1639+
val NoApprox = new ApproxState(0)
16281640

16291641
/** Show trace of comparison operations when performing `op` as result string */
16301642
def explained[T](op: Context => T)(implicit ctx: Context): String = {

0 commit comments

Comments
 (0)